@mastra/memory 1.24.0 → 1.25.0-alpha.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 (57) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/docs/SKILL.md +6 -6
  3. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  4. package/dist/docs/references/docs-agents-agent-approval.md +85 -11
  5. package/dist/docs/references/docs-agents-networks.md +2 -2
  6. package/dist/docs/references/docs-agents-supervisor-agents.md +19 -13
  7. package/dist/docs/references/docs-evals-evals-with-memory.md +4 -4
  8. package/dist/docs/references/docs-long-running-agents-background-tasks.md +10 -10
  9. package/dist/docs/references/docs-long-running-agents-goals.md +15 -11
  10. package/dist/docs/references/docs-memory-memory-processors.md +10 -10
  11. package/dist/docs/references/docs-memory-message-history.md +11 -5
  12. package/dist/docs/references/docs-memory-multi-user-threads.md +6 -6
  13. package/dist/docs/references/docs-memory-observational-memory.md +57 -38
  14. package/dist/docs/references/docs-memory-overview.md +24 -10
  15. package/dist/docs/references/docs-memory-semantic-recall.md +3 -3
  16. package/dist/docs/references/docs-memory-working-memory.md +8 -8
  17. package/dist/docs/references/docs-storage-overview.md +2 -2
  18. package/dist/docs/references/reference-memory-clone-utilities.md +1 -1
  19. package/dist/docs/references/reference-memory-cloneThread.md +3 -3
  20. package/dist/docs/references/reference-memory-listThreads.md +1 -1
  21. package/dist/docs/references/reference-memory-memory-class.md +4 -4
  22. package/dist/docs/references/reference-memory-observational-memory.md +88 -38
  23. package/dist/docs/references/reference-memory-summarizeConversation.md +3 -3
  24. package/dist/docs/references/reference-memory-summarizeThread.md +3 -3
  25. package/dist/docs/references/reference-processors-token-limiter-processor.md +4 -4
  26. package/dist/docs/references/reference-storage-dsql.md +3 -3
  27. package/dist/docs/references/reference-storage-dynamodb.md +7 -7
  28. package/dist/docs/references/reference-storage-mongodb.md +2 -2
  29. package/dist/docs/references/reference-storage-postgresql.md +2 -2
  30. package/dist/docs/references/reference-storage-redis.md +1 -1
  31. package/dist/docs/references/reference-storage-upstash.md +1 -1
  32. package/dist/docs/references/reference-vectors-libsql.md +2 -2
  33. package/dist/docs/references/reference-vectors-mongodb.md +3 -3
  34. package/dist/docs/references/reference-vectors-pg.md +5 -5
  35. package/dist/docs/references/reference-vectors-upstash.md +1 -1
  36. package/dist/index.cjs +1 -1
  37. package/dist/index.d.ts +1 -0
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +1 -1
  40. package/dist/processors/index.cjs +1 -1
  41. package/dist/processors/index.js +1 -1
  42. package/dist/processors/observational-memory/index.d.ts +1 -1
  43. package/dist/processors/observational-memory/index.d.ts.map +1 -1
  44. package/dist/processors/observational-memory/observation-strategies/types.d.ts +6 -0
  45. package/dist/processors/observational-memory/observation-strategies/types.d.ts.map +1 -1
  46. package/dist/processors/observational-memory/observation-turn/step.d.ts.map +1 -1
  47. package/dist/processors/observational-memory/observational-memory.d.ts +30 -1
  48. package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
  49. package/dist/processors/observational-memory/processor.d.ts.map +1 -1
  50. package/dist/processors/observational-memory/reflector-runner.d.ts.map +1 -1
  51. package/dist/processors/observational-memory/types.d.ts +50 -6
  52. package/dist/processors/observational-memory/types.d.ts.map +1 -1
  53. package/dist/{src-Ci_GvBVm.js → src-BYZh9IBv.js} +171 -27
  54. package/dist/{src-Ci_GvBVm.js.map → src-BYZh9IBv.js.map} +1 -1
  55. package/dist/{src-VD6qMn-H.cjs → src-naeQog_T.cjs} +171 -27
  56. package/dist/{src-VD6qMn-H.cjs.map → src-naeQog_T.cjs.map} +1 -1
  57. package/package.json +7 -7
@@ -20815,7 +20815,10 @@ var ObservationStrategy = class ObservationStrategy {
20815
20815
  await this.persistMarkerToStorage(failedMarkerForStorage, threadId, this.opts.resourceId).catch(() => {});
20816
20816
  if (abortSignal?.aborted) throw error;
20817
20817
  omError("[OM] Observation failed", error);
20818
- return { observed: false };
20818
+ return {
20819
+ observed: false,
20820
+ error: error instanceof Error ? error : new Error(String(error))
20821
+ };
20819
20822
  }
20820
20823
  omError("[OM] Observation failed", error);
20821
20824
  throw error;
@@ -21865,7 +21868,12 @@ var ObservationStep = class {
21865
21868
  currentModel: this.turn.actorModelContext,
21866
21869
  requestContext: this.turn.requestContext,
21867
21870
  observabilityContext: this.turn.observabilityContext,
21868
- lastActivityAt: getLastActivityFromMessages(messageList.get.all.db())
21871
+ lastActivityAt: getLastActivityFromMessages(messageList.get.all.db()),
21872
+ reflectionHooks: om.composeHooks(void 0, {
21873
+ threadId,
21874
+ resourceId,
21875
+ trigger: "turn-sync"
21876
+ })
21869
21877
  });
21870
21878
  await this.turn.refreshRecord();
21871
21879
  if (this.turn.record.generationCount > preReflectGeneration) reflected = true;
@@ -22025,7 +22033,12 @@ var ObservationStep = class {
22025
22033
  currentModel: this.turn.actorModelContext,
22026
22034
  requestContext: this.turn.requestContext,
22027
22035
  observabilityContext: this.turn.observabilityContext,
22028
- lastActivityAt: getLastActivityFromMessages(messageList.get.all.db())
22036
+ lastActivityAt: getLastActivityFromMessages(messageList.get.all.db()),
22037
+ reflectionHooks: om.composeHooks(void 0, {
22038
+ threadId,
22039
+ resourceId,
22040
+ trigger: "turn-sync"
22041
+ })
22029
22042
  });
22030
22043
  return {
22031
22044
  succeeded: true,
@@ -22038,6 +22051,7 @@ var ObservationStep = class {
22038
22051
  threadId,
22039
22052
  resourceId,
22040
22053
  messages: messageList.get.all.db(),
22054
+ trigger: "turn-sync",
22041
22055
  requestContext: this.turn.requestContext,
22042
22056
  writer: this.turn.writer,
22043
22057
  observabilityContext: this.turn.observabilityContext
@@ -22869,12 +22883,16 @@ var ReflectorRunner = class {
22869
22883
  });
22870
22884
  reflectionHooks?.onReflectionStart?.();
22871
22885
  const asyncOp = this.doAsyncBufferedReflection(record, bufferKey, writer, requestContext, observabilityContext, priorExtractedValues, mainAgent, sendSignal).then((outcome) => {
22872
- reflectionHooks?.onReflectionEnd?.({
22873
- usage: outcome?.usage,
22874
- ...outcome?.providerMetadata ? { providerMetadata: outcome.providerMetadata } : {}
22875
- });
22876
- }).catch(async (error) => {
22877
- if (writer) {
22886
+ try {
22887
+ reflectionHooks?.onReflectionEnd?.({
22888
+ usage: outcome?.usage,
22889
+ ...outcome?.providerMetadata ? { providerMetadata: outcome.providerMetadata } : {}
22890
+ });
22891
+ } catch (hookError) {
22892
+ omError("[OM] onReflectionEnd hook failed after async buffered reflection", hookError);
22893
+ }
22894
+ }, async (error) => {
22895
+ if (writer) try {
22878
22896
  const failedMarker = createBufferingFailedMarker({
22879
22897
  cycleId: `reflect-buf-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
22880
22898
  operationType: "reflection",
@@ -22889,12 +22907,18 @@ var ReflectorRunner = class {
22889
22907
  transient: true
22890
22908
  }).catch(() => {});
22891
22909
  await this.persistMarkerToStorage(failedMarker, record.threadId ?? "", record.resourceId ?? void 0);
22910
+ } catch (markerError) {
22911
+ omError("[OM] Failed to persist buffering-failed marker after async buffered reflection failure", markerError);
22892
22912
  }
22893
22913
  omError("[OM] Async buffered reflection failed", error);
22894
- reflectionHooks?.onReflectionEnd?.({
22895
- usage: void 0,
22896
- error: error instanceof Error ? error : new Error(String(error))
22897
- });
22914
+ try {
22915
+ reflectionHooks?.onReflectionEnd?.({
22916
+ usage: void 0,
22917
+ error: error instanceof Error ? error : new Error(String(error))
22918
+ });
22919
+ } catch (hookError) {
22920
+ omError("[OM] onReflectionEnd hook failed after async buffered reflection failure", hookError);
22921
+ }
22898
22922
  BufferingCoordinator.lastBufferedBoundary.delete(bufferKey);
22899
22923
  }).finally(() => {
22900
22924
  BufferingCoordinator.asyncBufferingOps.delete(bufferKey);
@@ -23141,7 +23165,6 @@ var ReflectorRunner = class {
23141
23165
  return;
23142
23166
  }
23143
23167
  }
23144
- reflectionHooks?.onReflectionStart?.();
23145
23168
  await this.storage.setReflectingFlag(record.id, true);
23146
23169
  registerOp(record.id, "reflecting");
23147
23170
  const cycleId = crypto.randomUUID();
@@ -23182,6 +23205,7 @@ var ReflectorRunner = class {
23182
23205
  let reflectionUsage;
23183
23206
  let reflectionProviderMetadata;
23184
23207
  let reflectionError;
23208
+ reflectionHooks?.onReflectionStart?.();
23185
23209
  try {
23186
23210
  const compressionStartLevel = await this.getCompressionStartLevel(requestContext);
23187
23211
  const reflectResult = await this.call(record.activeObservations, void 0, streamContext, reflectThreshold, abortSignal, void 0, compressionStartLevel, requestContext, priorExtractedValues, observabilityContext, void 0, mainAgent, sendSignal);
@@ -23245,12 +23269,15 @@ var ReflectorRunner = class {
23245
23269
  omError("[OM] Reflection failed", error);
23246
23270
  } finally {
23247
23271
  await this.storage.setReflectingFlag(record.id, false);
23248
- reflectionHooks?.onReflectionEnd?.({
23249
- usage: reflectionUsage,
23250
- error: reflectionError,
23251
- ...reflectionProviderMetadata ? { providerMetadata: reflectionProviderMetadata } : {}
23252
- });
23253
- unregisterOp(record.id, "reflecting");
23272
+ try {
23273
+ reflectionHooks?.onReflectionEnd?.({
23274
+ usage: reflectionUsage,
23275
+ error: reflectionError,
23276
+ ...reflectionProviderMetadata ? { providerMetadata: reflectionProviderMetadata } : {}
23277
+ });
23278
+ } finally {
23279
+ unregisterOp(record.id, "reflecting");
23280
+ }
23254
23281
  }
23255
23282
  }
23256
23283
  };
@@ -23703,6 +23730,8 @@ var ObservationalMemory = class ObservationalMemory {
23703
23730
  reflectionConfig;
23704
23731
  onDebugEvent;
23705
23732
  onIndexObservations;
23733
+ /** Config-level lifecycle hooks fired for every observation/reflection cycle. */
23734
+ hooks;
23706
23735
  /** Observer agent runner — handles LLM calls for extracting observations. */
23707
23736
  observer;
23708
23737
  /** Reflector agent runner — handles LLM calls for compressing observations. */
@@ -23763,6 +23792,7 @@ var ObservationalMemory = class ObservationalMemory {
23763
23792
  this.scope = config.scope ?? "thread";
23764
23793
  this.retrieval = Boolean(config.retrieval);
23765
23794
  this.onIndexObservations = config.onIndexObservations;
23795
+ this.hooks = config.hooks;
23766
23796
  this.mastra = config.mastra;
23767
23797
  this.memory = config.memory;
23768
23798
  const resolveModel = (model, defaultModel) => model === "default" ? defaultModel : model;
@@ -24684,7 +24714,11 @@ ${formattedMessages}
24684
24714
  transient: true
24685
24715
  }).catch(() => {});
24686
24716
  omDebug(`[OM:bufferInput] cycleId=${cycleId}, msgCount=${messagesToBuffer.length}, msgTokens=${tokensToBuffer}, ids=${messagesToBuffer.map((m) => `${m.id?.slice(0, 8)}@${m.createdAt ? new Date(m.createdAt).toISOString() : "none"}`).join(",")}`);
24687
- await ObservationStrategy.create(this, {
24717
+ await this.runBufferedObservationCycle({
24718
+ threadId,
24719
+ resourceId: freshRecord.resourceId ?? void 0,
24720
+ trigger: "async-buffer"
24721
+ }, () => ObservationStrategy.create(this, {
24688
24722
  record: freshRecord,
24689
24723
  threadId,
24690
24724
  resourceId: freshRecord.resourceId ?? void 0,
@@ -24694,7 +24728,7 @@ ${formattedMessages}
24694
24728
  writer,
24695
24729
  requestContext,
24696
24730
  observabilityContext
24697
- }).run();
24731
+ }).run());
24698
24732
  const maxTs = this.getMaxMessageTimestamp(messagesToBuffer);
24699
24733
  const cursor = new Date(maxTs.getTime() + 1);
24700
24734
  BufferingCoordinator.lastBufferedAtTime.set(bufferKey, cursor);
@@ -25267,7 +25301,11 @@ ${formattedMessages}
25267
25301
  ...startMarker,
25268
25302
  transient: true
25269
25303
  }).catch(() => {});
25270
- await ObservationStrategy.create(this, {
25304
+ await this.runBufferedObservationCycle({
25305
+ threadId,
25306
+ resourceId: record.resourceId ?? resourceId,
25307
+ trigger: "async-buffer"
25308
+ }, () => ObservationStrategy.create(this, {
25271
25309
  record,
25272
25310
  threadId,
25273
25311
  resourceId: record.resourceId ?? void 0,
@@ -25280,7 +25318,7 @@ ${formattedMessages}
25280
25318
  requestContext,
25281
25319
  currentModel: opts.currentModel,
25282
25320
  observabilityContext
25283
- }).run();
25321
+ }).run());
25284
25322
  if (isOmReproCaptureEnabled()) writeObserverExchangeReproCapture({
25285
25323
  threadId,
25286
25324
  resourceId: record.resourceId ?? void 0,
@@ -25490,6 +25528,88 @@ ${formattedMessages}
25490
25528
  };
25491
25529
  }
25492
25530
  /**
25531
+ * Compose the config-level hooks with optional per-call hooks into a single
25532
+ * `ObserveHooks` object, binding call context onto the config-level
25533
+ * callbacks. Config-level hooks are guarded so a throwing consumer hook can
25534
+ * never fail an observation/reflection cycle; per-call hooks keep their
25535
+ * existing payloads and propagation semantics. Returns undefined when
25536
+ * neither is configured, so call sites stay zero-cost.
25537
+ *
25538
+ * Used internally by every pipeline path (manual observe/reflect,
25539
+ * turn-engine sync observation, async buffering); public only so the
25540
+ * observation turn engine can thread config-level reflection hooks into
25541
+ * reflector calls.
25542
+ *
25543
+ * @internal
25544
+ */
25545
+ composeHooks(callHooks, context) {
25546
+ const configHooks = this.hooks;
25547
+ if (!configHooks) return callHooks;
25548
+ if (!callHooks && !Object.keys(configHooks).length) return void 0;
25549
+ const fireConfigHook = (name, arg) => {
25550
+ const hook = configHooks[name];
25551
+ if (!hook) return;
25552
+ const logHookFailure = (error) => omDebug(`[OM:hooks] config-level ${name} hook failed: ${error instanceof Error ? error.message : String(error)}`);
25553
+ try {
25554
+ const out = hook(arg);
25555
+ if (out && typeof out.then === "function") out.then(void 0, logHookFailure);
25556
+ } catch (error) {
25557
+ logHookFailure(error);
25558
+ }
25559
+ };
25560
+ return {
25561
+ onObservationStart: () => {
25562
+ fireConfigHook("onObservationStart", context);
25563
+ callHooks?.onObservationStart?.();
25564
+ },
25565
+ onObservationEnd: (result) => {
25566
+ fireConfigHook("onObservationEnd", {
25567
+ ...context,
25568
+ ...result
25569
+ });
25570
+ callHooks?.onObservationEnd?.(result);
25571
+ },
25572
+ onReflectionStart: () => {
25573
+ fireConfigHook("onReflectionStart", context);
25574
+ callHooks?.onReflectionStart?.();
25575
+ },
25576
+ onReflectionEnd: (result) => {
25577
+ fireConfigHook("onReflectionEnd", {
25578
+ ...context,
25579
+ ...result
25580
+ });
25581
+ callHooks?.onReflectionEnd?.(result);
25582
+ }
25583
+ };
25584
+ }
25585
+ /**
25586
+ * Run one buffered observation cycle, firing config-level hooks around it.
25587
+ * Shared by both async-buffer lanes — buffer() and
25588
+ * runAsyncBufferedObservation() — whose fire-and-forget callers never see
25589
+ * the strategy result. The async-buffer strategy swallows failures
25590
+ * (rethrowOnFailure=false) and surfaces them on the result instead, so the
25591
+ * end hook reports `error` for failed cycles even though nothing throws.
25592
+ */
25593
+ async runBufferedObservationCycle(context, run) {
25594
+ const hooks = this.composeHooks(void 0, context);
25595
+ hooks?.onObservationStart?.();
25596
+ let runResult;
25597
+ let runError;
25598
+ try {
25599
+ runResult = await run();
25600
+ return runResult;
25601
+ } catch (error) {
25602
+ runError = error instanceof Error ? error : new Error(String(error));
25603
+ throw error;
25604
+ } finally {
25605
+ hooks?.onObservationEnd?.({
25606
+ usage: runResult?.usage,
25607
+ error: runError ?? runResult?.error,
25608
+ ...runResult?.providerMetadata ? { providerMetadata: runResult.providerMetadata } : {}
25609
+ });
25610
+ }
25611
+ }
25612
+ /**
25493
25613
  * Manually trigger observation.
25494
25614
  *
25495
25615
  * When `messages` is provided, those are used directly (filtered for unobserved)
@@ -25500,8 +25620,13 @@ ${formattedMessages}
25500
25620
  * along with the updated record.
25501
25621
  */
25502
25622
  async observe(opts) {
25503
- const { threadId, resourceId, messages, hooks, requestContext } = opts;
25623
+ const { threadId, resourceId, messages, requestContext } = opts;
25504
25624
  const lockKey = this.buffering.getLockKey(threadId, resourceId);
25625
+ const hooks = this.composeHooks(opts.hooks, {
25626
+ threadId,
25627
+ resourceId,
25628
+ trigger: opts.trigger ?? "manual"
25629
+ });
25505
25630
  const reflectionHooks = hooks ? {
25506
25631
  onReflectionStart: hooks.onReflectionStart,
25507
25632
  onReflectionEnd: hooks.onReflectionEnd
@@ -25574,6 +25699,15 @@ ${formattedMessages}
25574
25699
  };
25575
25700
  await this.storage.setReflectingFlag(record.id, true);
25576
25701
  registerOp(record.id, "reflecting");
25702
+ const hooks = this.composeHooks(void 0, {
25703
+ threadId,
25704
+ resourceId,
25705
+ trigger: "manual"
25706
+ });
25707
+ hooks?.onReflectionStart?.();
25708
+ let reflectionUsage;
25709
+ let reflectionProviderMetadata;
25710
+ let reflectionError;
25577
25711
  try {
25578
25712
  const thread = await this.storage.getThreadById({ threadId });
25579
25713
  const previousOmMetadata = (0, _mastra_core_memory.getThreadOMMetadata)(thread?.metadata);
@@ -25603,12 +25737,16 @@ ${formattedMessages}
25603
25737
  metadata: newMetadata
25604
25738
  });
25605
25739
  }
25740
+ const updatedRecord = await this.getOrCreateRecord(threadId, resourceId);
25741
+ reflectionUsage = reflectResult.usage;
25742
+ reflectionProviderMetadata = reflectResult.providerMetadata;
25606
25743
  return {
25607
25744
  reflected: true,
25608
- record: await this.getOrCreateRecord(threadId, resourceId),
25745
+ record: updatedRecord,
25609
25746
  usage: reflectResult.usage
25610
25747
  };
25611
25748
  } catch (error) {
25749
+ reflectionError = error instanceof Error ? error : new Error(String(error));
25612
25750
  omError("[OM] reflect() failed", error);
25613
25751
  return {
25614
25752
  reflected: false,
@@ -25616,6 +25754,11 @@ ${formattedMessages}
25616
25754
  usage: void 0
25617
25755
  };
25618
25756
  } finally {
25757
+ hooks?.onReflectionEnd?.({
25758
+ usage: reflectionUsage,
25759
+ error: reflectionError,
25760
+ ...reflectionProviderMetadata ? { providerMetadata: reflectionProviderMetadata } : {}
25761
+ });
25619
25762
  await this.storage.setReflectingFlag(record.id, false);
25620
25763
  unregisterOp(record.id, "reflecting");
25621
25764
  }
@@ -27209,6 +27352,7 @@ ${workingMemory}`;
27209
27352
  model: omConfig.model,
27210
27353
  mastra: this._mastraInstance,
27211
27354
  onIndexObservations,
27355
+ hooks: omConfig.hooks,
27212
27356
  observation: omConfig.observation ? {
27213
27357
  model: omConfig.observation.model,
27214
27358
  messageTokens: omConfig.observation.messageTokens,
@@ -28357,4 +28501,4 @@ Object.defineProperty(exports, "wrapInObservationGroup", {
28357
28501
  }
28358
28502
  });
28359
28503
 
28360
- //# sourceMappingURL=src-VD6qMn-H.cjs.map
28504
+ //# sourceMappingURL=src-naeQog_T.cjs.map