@mastra/memory 1.11.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 (42) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +1 -1
  3. package/dist/{chunk-D4D6ZFBQ.js → chunk-DDQHE4NV.js} +65 -40
  4. package/dist/chunk-DDQHE4NV.js.map +1 -0
  5. package/dist/{chunk-VINRPDYQ.cjs → chunk-HLGFIN4J.cjs} +65 -40
  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 +43 -43
  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-FATH657E.cjs → observational-memory-34W4S4I5.cjs} +26 -26
  22. package/dist/{observational-memory-FATH657E.cjs.map → observational-memory-34W4S4I5.cjs.map} +1 -1
  23. package/dist/{observational-memory-SN7GKMHZ.js → observational-memory-B25SASRW.js} +3 -3
  24. package/dist/{observational-memory-SN7GKMHZ.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-groups.d.ts +2 -2
  28. package/dist/processors/observational-memory/observation-groups.d.ts.map +1 -1
  29. package/dist/processors/observational-memory/observation-strategies/async-buffer.d.ts +1 -0
  30. package/dist/processors/observational-memory/observation-strategies/async-buffer.d.ts.map +1 -1
  31. package/dist/processors/observational-memory/observation-strategies/base.d.ts +7 -2
  32. package/dist/processors/observational-memory/observation-strategies/base.d.ts.map +1 -1
  33. package/dist/processors/observational-memory/observation-strategies/resource-scoped.d.ts +1 -0
  34. package/dist/processors/observational-memory/observation-strategies/resource-scoped.d.ts.map +1 -1
  35. package/dist/processors/observational-memory/observation-strategies/sync.d.ts +1 -0
  36. package/dist/processors/observational-memory/observation-strategies/sync.d.ts.map +1 -1
  37. package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
  38. package/dist/processors/observational-memory/reflector-agent.d.ts.map +1 -1
  39. package/dist/tools/om-tools.d.ts.map +1 -1
  40. package/package.json +5 -5
  41. package/dist/chunk-D4D6ZFBQ.js.map +0 -1
  42. package/dist/chunk-VINRPDYQ.cjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # @mastra/memory
2
2
 
3
+ ## 1.12.0-alpha.1
4
+
5
+ ### Minor Changes
6
+
7
+ - Added more forgiving raw message browsing in the recall tool for agent follow-up calls. ([#14873](https://github.com/mastra-ai/mastra/pull/14873))
8
+
9
+ When an agent requests a `partIndex` greater than the highest visible part in a message, recall now returns the first visible part from the next visible message instead of failing. This makes it easier for agents using `recall` to keep browsing raw messages even when they guess the wrong part index.
10
+
11
+ ### Patch Changes
12
+
13
+ - Fixed synchronous observation error handling in Observational Memory. `observe()` now throws when synchronous (thread/resource-scoped) observation fails, instead of continuing silently with stale observations. Async buffered observation failures remain non-fatal. ([#14843](https://github.com/mastra-ai/mastra/pull/14843))
14
+
15
+ - Updated dependencies [[`9c57f2f`](https://github.com/mastra-ai/mastra/commit/9c57f2f7241e9f94769aa99fc86c531e8207d0f9), [`5bfc691`](https://github.com/mastra-ai/mastra/commit/5bfc69104c07ba7a9b55c2f8536422c0878b9c57)]:
16
+ - @mastra/core@1.19.0-alpha.2
17
+
18
+ ## 1.11.1-alpha.0
19
+
20
+ ### Patch Changes
21
+
22
+ - Fixed reflected observation groups so their metadata stays compact and marks reflection-derived content. ([#14791](https://github.com/mastra-ai/mastra/pull/14791))
23
+
24
+ - Updated dependencies [[`180aaaf`](https://github.com/mastra-ai/mastra/commit/180aaaf4d0903d33a49bc72de2d40ca69a5bc599)]:
25
+ - @mastra/core@1.18.1-alpha.0
26
+
3
27
  ## 1.11.0
4
28
 
5
29
  ### Minor Changes
package/README.md CHANGED
@@ -1,3 +1,3 @@
1
1
  # Mastra Memory
2
2
 
3
- Memory management for Mastra agents. Visit [the docs](https://mastra.ai/docs/agents/agent-memory) for more information.
3
+ Memory management for Mastra agents. Visit [the docs](https://mastra.ai/docs/memory/overview) for more information.
@@ -717,10 +717,10 @@ function stripReflectionGroupMetadata(body) {
717
717
  function generateAnchorId() {
718
718
  return randomBytes(8).toString("hex");
719
719
  }
720
- function wrapInObservationGroup(observations, range, id = generateAnchorId(), sourceGroupIds) {
720
+ function wrapInObservationGroup(observations, range, id = generateAnchorId(), _sourceGroupIds, kind) {
721
721
  const content = observations.trim();
722
- const sourceGroupIdsAttr = sourceGroupIds?.length ? ` source-group-ids="${sourceGroupIds.join(",")}"` : "";
723
- return `<observation-group id="${id}" range="${range}"${sourceGroupIdsAttr}>
722
+ const kindAttr = kind ? ` kind="${kind}"` : "";
723
+ return `<observation-group id="${id}" range="${range}"${kindAttr}>
724
724
  ${content}
725
725
  </observation-group>`;
726
726
  }
@@ -740,8 +740,8 @@ function parseObservationGroups(observations) {
740
740
  groups.push({
741
741
  id,
742
742
  range,
743
- content: match[2].trim(),
744
- sourceGroupIds: attributes["source-group-ids"]?.split(",").map((part) => part.trim()).filter(Boolean)
743
+ kind: attributes.kind,
744
+ content: match[2].trim()
745
745
  });
746
746
  }
747
747
  return groups;
@@ -752,12 +752,22 @@ function stripObservationGroups(observations) {
752
752
  }
753
753
  return observations.replace(OBSERVATION_GROUP_PATTERN, (_match, _attributes, content) => content.trim()).replace(/\n{3,}/g, "\n\n").trim();
754
754
  }
755
+ function getRangeSegments(range) {
756
+ return range.split(",").map((segment) => segment.trim()).filter(Boolean);
757
+ }
755
758
  function combineObservationGroupRanges(groups) {
756
- return Array.from(
757
- new Set(
758
- groups.flatMap((group) => group.range.split(",")).map((range) => range.trim()).filter(Boolean)
759
- )
760
- ).join(",");
759
+ const segments = groups.flatMap((group) => getRangeSegments(group.range));
760
+ if (segments.length === 0) {
761
+ return "";
762
+ }
763
+ const firstSegment = segments[0];
764
+ const lastSegment = segments[segments.length - 1];
765
+ const firstStart = firstSegment?.split(":")[0]?.trim();
766
+ const lastEnd = lastSegment?.split(":").at(-1)?.trim();
767
+ if (firstStart && lastEnd) {
768
+ return `${firstStart}:${lastEnd}`;
769
+ }
770
+ return Array.from(new Set(segments)).join(",");
761
771
  }
762
772
  function renderObservationGroupsForReflection(observations) {
763
773
  const groups = parseObservationGroups(observations);
@@ -794,15 +804,12 @@ function deriveObservationGroupProvenance(content, groups) {
794
804
  });
795
805
  const fallbackGroup = groups[Math.min(index, groups.length - 1)];
796
806
  const resolvedGroups = matchingGroups.length > 0 ? matchingGroups : fallbackGroup ? [fallbackGroup] : [];
797
- const sourceGroupIds = Array.from(
798
- new Set(resolvedGroups.flatMap((group) => [group.id, ...group.sourceGroupIds ?? []]))
799
- );
800
807
  const canonicalGroupId = getCanonicalGroupId(section.heading, index);
801
808
  return {
802
809
  id: canonicalGroupId,
803
810
  range: combineObservationGroupRanges(resolvedGroups),
804
- content: section.body,
805
- sourceGroupIds
811
+ kind: "reflection",
812
+ content: section.body
806
813
  };
807
814
  });
808
815
  }
@@ -817,13 +824,14 @@ function reconcileObservationGroupsFromReflection(content, sourceObservations) {
817
824
  }
818
825
  const derivedGroups = deriveObservationGroupProvenance(normalizedContent, sourceGroups);
819
826
  if (derivedGroups.length > 0) {
820
- return derivedGroups.map((group) => wrapInObservationGroup(group.content, group.range, group.id, group.sourceGroupIds)).join("\n\n");
827
+ return derivedGroups.map((group) => wrapInObservationGroup(group.content, group.range, group.id, void 0, group.kind)).join("\n\n");
821
828
  }
822
829
  return wrapInObservationGroup(
823
830
  normalizedContent,
824
831
  combineObservationGroupRanges(sourceGroups),
825
832
  generateAnchorId(),
826
- Array.from(new Set(sourceGroups.flatMap((group) => [group.id, ...group.sourceGroupIds ?? []])))
833
+ void 0,
834
+ "reflection"
827
835
  );
828
836
  }
829
837
 
@@ -935,7 +943,11 @@ var ObservationStrategy = class _ObservationStrategy {
935
943
  retrieval;
936
944
  /** Select the right strategy based on scope and mode. Wired up by index.ts. */
937
945
  static create;
938
- /** Run the full observation lifecycle. */
946
+ /**
947
+ * Run the full observation lifecycle.
948
+ * @returns `true` if a full observation cycle completed; `false` if skipped (stale lock) or async-buffer failure was swallowed.
949
+ * @throws On sync/resource-scoped observer failure after failed markers (same as pre–Option-A contract).
950
+ */
939
951
  async run() {
940
952
  const { record, threadId, abortSignal, writer, reflectionHooks, requestContext } = this.opts;
941
953
  const cycleId = this.generateCycleId();
@@ -943,7 +955,7 @@ var ObservationStrategy = class _ObservationStrategy {
943
955
  if (this.needsLock) {
944
956
  const fresh = await this.storage.getObservationalMemory(record.threadId, record.resourceId);
945
957
  if (fresh?.lastObservedAt && record.lastObservedAt && fresh.lastObservedAt > record.lastObservedAt) {
946
- return;
958
+ return false;
947
959
  }
948
960
  }
949
961
  const { messages, existingObservations } = await this.prepare();
@@ -964,23 +976,29 @@ var ObservationStrategy = class _ObservationStrategy {
964
976
  observabilityContext: this.opts.observabilityContext
965
977
  });
966
978
  }
979
+ return true;
967
980
  } catch (error) {
968
981
  await this.emitFailedMarkers(cycleId, error);
969
- const failedMarkerForStorage = {
970
- type: "data-om-observation-failed",
971
- data: {
972
- cycleId,
973
- operationType: "observation",
974
- startedAt: (/* @__PURE__ */ new Date()).toISOString(),
975
- error: error instanceof Error ? error.message : String(error),
976
- recordId: record.id,
977
- threadId
978
- }
979
- };
980
- await this.persistMarkerToStorage(failedMarkerForStorage, threadId, this.opts.resourceId).catch(() => {
981
- });
982
- if (abortSignal?.aborted) throw error;
982
+ if (!this.rethrowOnFailure) {
983
+ const failedMarkerForStorage = {
984
+ type: "data-om-observation-failed",
985
+ data: {
986
+ cycleId,
987
+ operationType: "observation",
988
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
989
+ error: error instanceof Error ? error.message : String(error),
990
+ recordId: record.id,
991
+ threadId
992
+ }
993
+ };
994
+ await this.persistMarkerToStorage(failedMarkerForStorage, threadId, this.opts.resourceId).catch(() => {
995
+ });
996
+ if (abortSignal?.aborted) throw error;
997
+ omError("[OM] Observation failed", error);
998
+ return false;
999
+ }
983
1000
  omError("[OM] Observation failed", error);
1001
+ throw error;
984
1002
  }
985
1003
  }
986
1004
  // ── Shared helpers ──────────────────────────────────────────
@@ -1201,6 +1219,9 @@ var SyncObservationStrategy = class extends ObservationStrategy {
1201
1219
  get needsReflection() {
1202
1220
  return true;
1203
1221
  }
1222
+ get rethrowOnFailure() {
1223
+ return true;
1224
+ }
1204
1225
  async prepare() {
1205
1226
  const { record, threadId, messages } = this.opts;
1206
1227
  this.deps.emitDebugEvent({
@@ -1394,6 +1415,9 @@ var AsyncBufferObservationStrategy = class extends ObservationStrategy {
1394
1415
  get needsReflection() {
1395
1416
  return false;
1396
1417
  }
1418
+ get rethrowOnFailure() {
1419
+ return false;
1420
+ }
1397
1421
  generateCycleId() {
1398
1422
  return this.cycleId;
1399
1423
  }
@@ -1530,6 +1554,9 @@ var ResourceScopedObservationStrategy = class extends ObservationStrategy {
1530
1554
  get needsReflection() {
1531
1555
  return true;
1532
1556
  }
1557
+ get rethrowOnFailure() {
1558
+ return true;
1559
+ }
1533
1560
  async prepare() {
1534
1561
  const { record, threadId: currentThreadId, messages: currentThreadMessages } = this.opts;
1535
1562
  const { threads: allThreads } = await this.storage.listThreads({ filter: { resourceId: this.resourceId } });
@@ -3821,11 +3848,10 @@ Aim for a 2/10 detail level. Fewer, more generic observations are better than ma
3821
3848
  };
3822
3849
  function buildReflectorPrompt(observations, manualPrompt, compressionLevel, skipContinuationHints) {
3823
3850
  const level = typeof compressionLevel === "number" ? compressionLevel : compressionLevel ? 1 : 0;
3824
- const reflectionView = renderObservationGroupsForReflection(observations) ?? observations;
3825
- const anchoredObservations = injectAnchorIds(reflectionView);
3851
+ const reflectionView = stripObservationGroups(observations);
3826
3852
  let prompt = `## OBSERVATIONS TO REFLECT ON
3827
3853
 
3828
- ${anchoredObservations}
3854
+ ${reflectionView}
3829
3855
 
3830
3856
  ---
3831
3857
 
@@ -7799,7 +7825,7 @@ ${grouped}` : grouped;
7799
7825
  }
7800
7826
  hooks?.onObservationStart?.();
7801
7827
  try {
7802
- await ObservationStrategy.create(this, {
7828
+ observed = await ObservationStrategy.create(this, {
7803
7829
  record: freshRecord,
7804
7830
  threadId,
7805
7831
  resourceId,
@@ -7809,7 +7835,6 @@ ${grouped}` : grouped;
7809
7835
  writer: opts.writer,
7810
7836
  observabilityContext: opts.observabilityContext
7811
7837
  }).run();
7812
- observed = true;
7813
7838
  } finally {
7814
7839
  hooks?.onObservationEnd?.();
7815
7840
  }
@@ -8418,5 +8443,5 @@ function getObservationsAsOf(activeObservations, asOf) {
8418
8443
  }
8419
8444
 
8420
8445
  export { ModelByInputTokens, OBSERVER_SYSTEM_PROMPT, ObservationalMemory, ObservationalMemoryProcessor, TokenCounter, buildObserverPrompt, buildObserverSystemPrompt, combineObservationGroupRanges, deriveObservationGroupProvenance, extractCurrentTask, formatMessagesForObserver, formatToolResultForObserver, getObservationsAsOf, hasCurrentTaskSection, injectAnchorIds, optimizeObservationsForContext, parseAnchorId, parseObservationGroups, parseObserverOutput, reconcileObservationGroupsFromReflection, renderObservationGroupsForReflection, resolveToolResultValue, stripEphemeralAnchorIds, stripObservationGroups, truncateStringByTokens, wrapInObservationGroup };
8421
- //# sourceMappingURL=chunk-D4D6ZFBQ.js.map
8422
- //# sourceMappingURL=chunk-D4D6ZFBQ.js.map
8446
+ //# sourceMappingURL=chunk-DDQHE4NV.js.map
8447
+ //# sourceMappingURL=chunk-DDQHE4NV.js.map