@mastra/memory 1.16.0-alpha.1 → 1.16.0-alpha.2

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 (37) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/{chunk-3NECGYWZ.cjs → chunk-EOHXGI4J.cjs} +149 -14
  3. package/dist/chunk-EOHXGI4J.cjs.map +1 -0
  4. package/dist/{chunk-HB6AYAFD.js → chunk-MGHUIRKN.js} +149 -14
  5. package/dist/chunk-MGHUIRKN.js.map +1 -0
  6. package/dist/docs/SKILL.md +1 -1
  7. package/dist/docs/assets/SOURCE_MAP.json +47 -47
  8. package/dist/docs/references/docs-memory-observational-memory.md +4 -0
  9. package/dist/index.cjs +14 -13
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.ts +1 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +5 -4
  14. package/dist/index.js.map +1 -1
  15. package/dist/{observational-memory-X4N2R4CA.cjs → observational-memory-FCDIQ3SX.cjs} +26 -26
  16. package/dist/{observational-memory-X4N2R4CA.cjs.map → observational-memory-FCDIQ3SX.cjs.map} +1 -1
  17. package/dist/{observational-memory-WWAB2MMI.js → observational-memory-WJ4BDRUP.js} +3 -3
  18. package/dist/{observational-memory-WWAB2MMI.js.map → observational-memory-WJ4BDRUP.js.map} +1 -1
  19. package/dist/processors/index.cjs +24 -24
  20. package/dist/processors/index.js +1 -1
  21. package/dist/processors/observational-memory/markers.d.ts +3 -1
  22. package/dist/processors/observational-memory/markers.d.ts.map +1 -1
  23. package/dist/processors/observational-memory/model-context.d.ts +10 -0
  24. package/dist/processors/observational-memory/model-context.d.ts.map +1 -0
  25. package/dist/processors/observational-memory/observation-turn/step.d.ts.map +1 -1
  26. package/dist/processors/observational-memory/observation-turn/turn.d.ts +3 -0
  27. package/dist/processors/observational-memory/observation-turn/turn.d.ts.map +1 -1
  28. package/dist/processors/observational-memory/observational-memory.d.ts +9 -1
  29. package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
  30. package/dist/processors/observational-memory/processor.d.ts.map +1 -1
  31. package/dist/processors/observational-memory/reflector-runner.d.ts +5 -2
  32. package/dist/processors/observational-memory/reflector-runner.d.ts.map +1 -1
  33. package/dist/processors/observational-memory/types.d.ts +19 -2
  34. package/dist/processors/observational-memory/types.d.ts.map +1 -1
  35. package/package.json +4 -4
  36. package/dist/chunk-3NECGYWZ.cjs.map +0 -1
  37. package/dist/chunk-HB6AYAFD.js.map +0 -1
@@ -201,6 +201,19 @@ var BufferingCoordinator = class _BufferingCoordinator {
201
201
  }
202
202
  };
203
203
 
204
+ // src/processors/observational-memory/model-context.ts
205
+ function didProviderChange(actorModel, lastModel) {
206
+ if (actorModel === void 0 || lastModel === void 0) return false;
207
+ const actorHasSlash = actorModel.includes("/");
208
+ const lastHasSlash = lastModel.includes("/");
209
+ if (actorHasSlash && lastHasSlash) {
210
+ return actorModel !== lastModel;
211
+ }
212
+ const actorModelId = actorHasSlash ? actorModel.slice(actorModel.indexOf("/") + 1) : actorModel;
213
+ const lastModelId = lastHasSlash ? lastModel.slice(lastModel.indexOf("/") + 1) : lastModel;
214
+ return actorModelId !== lastModelId;
215
+ }
216
+
204
217
  // src/processors/observational-memory/date-utils.ts
205
218
  function formatRelativeTime(date, currentDate) {
206
219
  const diffMs = currentDate.getTime() - date.getTime();
@@ -487,7 +500,9 @@ function createActivationMarker(params) {
487
500
  observations: params.observations,
488
501
  triggeredBy: params.triggeredBy,
489
502
  lastActivityAt: params.lastActivityAt,
490
- ttlExpiredMs: params.ttlExpiredMs
503
+ ttlExpiredMs: params.ttlExpiredMs,
504
+ previousModel: params.previousModel,
505
+ currentModel: params.currentModel
491
506
  }
492
507
  };
493
508
  }
@@ -1982,6 +1997,7 @@ var ObservationStep = class {
1982
1997
  resourceId,
1983
1998
  checkThreshold: true,
1984
1999
  messages: step0Messages,
2000
+ currentModel: this.turn.actorModelContext,
1985
2001
  writer: this.turn.writer,
1986
2002
  messageList
1987
2003
  });
@@ -2005,6 +2021,8 @@ var ObservationStep = class {
2005
2021
  observationTokens: obsTokens,
2006
2022
  threadId,
2007
2023
  writer: this.turn.writer,
2024
+ messageList,
2025
+ currentModel: this.turn.actorModelContext,
2008
2026
  requestContext: this.turn.requestContext,
2009
2027
  observabilityContext: this.turn.observabilityContext,
2010
2028
  lastActivityAt: getLastActivityFromMessages(messageList.get.all.db())
@@ -2171,6 +2189,7 @@ var ObservationStep = class {
2171
2189
  threadId,
2172
2190
  resourceId,
2173
2191
  messages: messageList.get.all.db(),
2192
+ currentModel: this.turn.actorModelContext,
2174
2193
  writer: this.turn.writer,
2175
2194
  messageList
2176
2195
  });
@@ -2182,6 +2201,7 @@ var ObservationStep = class {
2182
2201
  threadId,
2183
2202
  writer: this.turn.writer,
2184
2203
  messageList,
2204
+ currentModel: this.turn.actorModelContext,
2185
2205
  requestContext: this.turn.requestContext,
2186
2206
  observabilityContext: this.turn.observabilityContext,
2187
2207
  lastActivityAt: getLastActivityFromMessages(messageList.get.all.db())
@@ -2226,6 +2246,8 @@ var ObservationTurn = class {
2226
2246
  requestContext;
2227
2247
  /** Optional observability context for nested OM spans. */
2228
2248
  observabilityContext;
2249
+ /** Current actor model for this step. Updated by the processor before prepare(). */
2250
+ actorModelContext;
2229
2251
  /** Optional processor-provided hooks for turn/step lifecycle integration. */
2230
2252
  hooks;
2231
2253
  constructor(opts) {
@@ -4094,12 +4116,44 @@ function validateCompression(reflectedTokens, targetThreshold) {
4094
4116
  }
4095
4117
 
4096
4118
  // src/processors/observational-memory/reflector-runner.ts
4119
+ function formatModelContext(provider, modelId) {
4120
+ if (provider && modelId) {
4121
+ return `${provider}/${modelId}`;
4122
+ }
4123
+ return modelId;
4124
+ }
4125
+ function getCurrentModel(model) {
4126
+ return formatModelContext(model?.provider, model?.modelId);
4127
+ }
4128
+ function getLastModelFromMessageList(messageList) {
4129
+ const messages = messageList?.get.all.db();
4130
+ if (!messages) return void 0;
4131
+ for (let i = messages.length - 1; i >= 0; i--) {
4132
+ const message = messages[i];
4133
+ if (!message || message.role !== "assistant" || !message.content || typeof message.content === "string") {
4134
+ continue;
4135
+ }
4136
+ for (let j = message.content.parts.length - 1; j >= 0; j--) {
4137
+ const part = message.content.parts[j];
4138
+ if (part?.type === "step-start" && typeof part.model === "string" && part.model.length > 0) {
4139
+ return part.model;
4140
+ }
4141
+ }
4142
+ const metadata = message.content.metadata;
4143
+ const model = formatModelContext(metadata?.provider, metadata?.modelId);
4144
+ if (model) {
4145
+ return model;
4146
+ }
4147
+ }
4148
+ return void 0;
4149
+ }
4097
4150
  async function withAbortCheck(fn, abortSignal) {
4098
4151
  if (abortSignal?.aborted) throw new Error("The operation was aborted.");
4099
4152
  const result = await fn();
4100
4153
  if (abortSignal?.aborted) throw new Error("The operation was aborted.");
4101
4154
  return result;
4102
4155
  }
4156
+ var EARLY_ACTIVATION_SIZE_FLOOR_RATIO = 0.75;
4103
4157
  var ReflectorRunner = class {
4104
4158
  reflectionConfig;
4105
4159
  observationConfig;
@@ -4424,7 +4478,9 @@ var ReflectorRunner = class {
4424
4478
  }
4425
4479
  /**
4426
4480
  * Try to activate buffered reflection when threshold is reached.
4427
- * Returns true if activation succeeded.
4481
+ * Returns a discriminated result so the caller can distinguish between
4482
+ * "activated", "no buffer present", and "suppressed by overshoot guard"
4483
+ * without re-deriving that state.
4428
4484
  */
4429
4485
  async tryActivateBufferedReflection(record, lockKey, writer, messageList, activationMetadata) {
4430
4486
  const bufferKey = this.buffering.getReflectionBufferKey(lockKey);
@@ -4447,8 +4503,8 @@ var ReflectorRunner = class {
4447
4503
  `[OM:reflect] tryActivateBufferedReflection: freshRecord.id=${freshRecord?.id}, freshBufferedReflection=${freshRecord?.bufferedReflection ? "present (" + freshRecord.bufferedReflection.length + " chars)" : "empty"}, freshObsTokens=${freshRecord?.observationTokenCount}`
4448
4504
  );
4449
4505
  if (!freshRecord?.bufferedReflection) {
4450
- omDebug(`[OM:reflect] tryActivateBufferedReflection: no buffered reflection after re-fetch, returning false`);
4451
- return false;
4506
+ omDebug(`[OM:reflect] tryActivateBufferedReflection: no buffered reflection after re-fetch`);
4507
+ return { status: "no-buffer" };
4452
4508
  }
4453
4509
  const beforeTokens = freshRecord.observationTokenCount ?? 0;
4454
4510
  const reflectedLineCount = freshRecord.reflectedObservationLineCount ?? 0;
@@ -4460,6 +4516,26 @@ var ReflectorRunner = class {
4460
4516
 
4461
4517
  ${unreflectedContent}` : freshRecord.bufferedReflection;
4462
4518
  const combinedTokenCount = this.tokenCounter.countObservations(combinedObservations);
4519
+ if (activationMetadata?.triggeredBy === "ttl" || activationMetadata?.triggeredBy === "provider_change") {
4520
+ const unreflectedTailTokens = unreflectedContent ? this.tokenCounter.countObservations(unreflectedContent) : 0;
4521
+ const bufferedReflectionTokens = freshRecord.bufferedReflectionTokens ?? 0;
4522
+ if (unreflectedTailTokens < bufferedReflectionTokens) {
4523
+ omDebug(
4524
+ `[OM:reflect] tryActivateBufferedReflection: suppressing early ${activationMetadata.triggeredBy} activation \u2014 unreflectedTailTokens=${unreflectedTailTokens} < bufferedReflectionTokens=${bufferedReflectionTokens}; keeping buffer for threshold activation`
4525
+ );
4526
+ return { status: "suppressed", reason: "composition" };
4527
+ }
4528
+ const bufferActivation = this.reflectionConfig.bufferActivation;
4529
+ const reflectThreshold = getMaxThreshold(this.getEffectiveReflectionTokens(freshRecord));
4530
+ const regularActivationTarget = reflectThreshold * (1 - bufferActivation);
4531
+ const minCombinedTokens = Math.round(regularActivationTarget * EARLY_ACTIVATION_SIZE_FLOOR_RATIO);
4532
+ if (combinedTokenCount < minCombinedTokens) {
4533
+ omDebug(
4534
+ `[OM:reflect] tryActivateBufferedReflection: suppressing early ${activationMetadata.triggeredBy} activation \u2014 combinedTokenCount=${combinedTokenCount} < minCombinedTokens=${minCombinedTokens} (${EARLY_ACTIVATION_SIZE_FLOOR_RATIO * 100}% of regular activation target ${Math.round(regularActivationTarget)}, threshold=${reflectThreshold}, bufferActivation=${bufferActivation}); keeping buffer for threshold activation`
4535
+ );
4536
+ return { status: "suppressed", reason: "size" };
4537
+ }
4538
+ }
4463
4539
  omDebug(
4464
4540
  `[OM:reflect] tryActivateBufferedReflection: activating, beforeTokens=${beforeTokens}, combinedTokenCount=${combinedTokenCount}, reflectedLineCount=${reflectedLineCount}, unreflectedLines=${unreflectedLines.length}`
4465
4541
  );
@@ -4489,6 +4565,8 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
4489
4565
  triggeredBy: activationMetadata?.triggeredBy,
4490
4566
  lastActivityAt: activationMetadata?.lastActivityAt,
4491
4567
  ttlExpiredMs: activationMetadata?.ttlExpiredMs,
4568
+ previousModel: activationMetadata?.previousModel,
4569
+ currentModel: activationMetadata?.currentModel,
4492
4570
  config: this.getObservationMarkerConfig(freshRecord)
4493
4571
  });
4494
4572
  void writer.custom(activationMarker).catch(() => {
@@ -4501,7 +4579,7 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
4501
4579
  );
4502
4580
  }
4503
4581
  BufferingCoordinator.reflectionBufferCycleIds.delete(bufferKey);
4504
- return true;
4582
+ return { status: "activated" };
4505
4583
  }
4506
4584
  /**
4507
4585
  * Check if reflection needed and trigger if so.
@@ -4515,6 +4593,7 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
4515
4593
  writer,
4516
4594
  abortSignal,
4517
4595
  messageList,
4596
+ currentModel,
4518
4597
  reflectionHooks,
4519
4598
  requestContext,
4520
4599
  observabilityContext,
@@ -4554,13 +4633,19 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
4554
4633
  const activateAfterIdle = this.reflectionConfig.activateAfterIdle;
4555
4634
  const ttlExpiredMs = activateAfterIdle !== void 0 && lastActivityAt !== void 0 ? Date.now() - lastActivityAt : void 0;
4556
4635
  const ttlExpired = ttlExpiredMs !== void 0 && activateAfterIdle !== void 0 && ttlExpiredMs >= activateAfterIdle;
4557
- if (observationTokens < reflectThreshold && !ttlExpired) {
4636
+ const actorModel = getCurrentModel(currentModel);
4637
+ const lastModel = getLastModelFromMessageList(messageList);
4638
+ const providerChanged = this.reflectionConfig.activateOnProviderChange === true && didProviderChange(actorModel, lastModel);
4639
+ if (observationTokens < reflectThreshold && !ttlExpired && !providerChanged) {
4558
4640
  return;
4559
4641
  }
4642
+ const activationTriggeredBy = observationTokens >= reflectThreshold ? "threshold" : providerChanged ? "provider_change" : "ttl";
4560
4643
  const activationMetadata = {
4561
- triggeredBy: ttlExpired ? "ttl" : "threshold",
4562
- lastActivityAt: ttlExpired ? lastActivityAt : void 0,
4563
- ttlExpiredMs: ttlExpired ? ttlExpiredMs : void 0
4644
+ triggeredBy: activationTriggeredBy,
4645
+ lastActivityAt: activationTriggeredBy === "ttl" ? lastActivityAt : void 0,
4646
+ ttlExpiredMs: activationTriggeredBy === "ttl" ? ttlExpiredMs : void 0,
4647
+ previousModel: activationTriggeredBy === "provider_change" ? lastModel : void 0,
4648
+ currentModel: activationTriggeredBy === "provider_change" ? actorModel : void 0
4564
4649
  };
4565
4650
  if (record.isReflecting) {
4566
4651
  if (isOpActiveInProcess(record.id, "reflecting")) {
@@ -4571,14 +4656,20 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
4571
4656
  await this.storage.setReflectingFlag(record.id, false);
4572
4657
  }
4573
4658
  if (this.buffering.isAsyncReflectionEnabled()) {
4574
- const activationSuccess = await this.tryActivateBufferedReflection(
4659
+ const activationResult = await this.tryActivateBufferedReflection(
4575
4660
  record,
4576
4661
  lockKey,
4577
4662
  writer,
4578
4663
  messageList,
4579
4664
  activationMetadata
4580
4665
  );
4581
- if (activationSuccess) {
4666
+ if (activationResult.status === "activated") {
4667
+ return;
4668
+ }
4669
+ if (activationResult.status === "suppressed") {
4670
+ omDebug(
4671
+ `[OM:reflect] skipping sync fallback / re-buffer after suppressed early ${activationMetadata.triggeredBy} activation (reason=${activationResult.reason})`
4672
+ );
4582
4673
  return;
4583
4674
  }
4584
4675
  if (this.reflectionConfig.blockAfter && observationTokens >= this.reflectionConfig.blockAfter) {
@@ -6279,6 +6370,36 @@ function getLastActivityFromMessages(messages) {
6279
6370
  }
6280
6371
  return void 0;
6281
6372
  }
6373
+ function formatModelContext2(provider, modelId) {
6374
+ if (provider && modelId) {
6375
+ return `${provider}/${modelId}`;
6376
+ }
6377
+ return modelId;
6378
+ }
6379
+ function getLastModelFromMessages(messages) {
6380
+ if (!messages) return void 0;
6381
+ for (let i = messages.length - 1; i >= 0; i--) {
6382
+ const message = messages[i];
6383
+ if (!message || message.role !== "assistant" || !message.content || typeof message.content === "string") {
6384
+ continue;
6385
+ }
6386
+ for (let j = message.content.parts.length - 1; j >= 0; j--) {
6387
+ const part = message.content.parts[j];
6388
+ if (part?.type === "step-start" && typeof part.model === "string" && part.model.length > 0) {
6389
+ return part.model;
6390
+ }
6391
+ }
6392
+ const metadata = message.content.metadata;
6393
+ const model = formatModelContext2(metadata?.provider, metadata?.modelId);
6394
+ if (model) {
6395
+ return model;
6396
+ }
6397
+ }
6398
+ return void 0;
6399
+ }
6400
+ function getCurrentModel2(model) {
6401
+ return formatModelContext2(model?.provider, model?.modelId);
6402
+ }
6282
6403
  function parseActivationTTL(value, fieldPath) {
6283
6404
  if (value === void 0) {
6284
6405
  return void 0;
@@ -6455,6 +6576,7 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
6455
6576
  ),
6456
6577
  bufferActivation: asyncBufferingDisabled ? void 0 : config.observation?.bufferActivation ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.bufferActivation,
6457
6578
  activateAfterIdle: parseActivationTTL(config.activateAfterIdle, "activateAfterIdle"),
6579
+ activateOnProviderChange: config.activateOnProviderChange ?? false,
6458
6580
  blockAfter: asyncBufferingDisabled ? void 0 : resolveBlockAfter(
6459
6581
  config.observation?.blockAfter ?? (config.observation?.bufferTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.bufferTokens ? 1.2 : void 0),
6460
6582
  config.observation?.messageTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.messageTokens
@@ -6474,6 +6596,7 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
6474
6596
  providerOptions: config.reflection?.providerOptions ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.providerOptions,
6475
6597
  bufferActivation: asyncBufferingDisabled ? void 0 : config?.reflection?.bufferActivation ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.bufferActivation,
6476
6598
  activateAfterIdle: parseActivationTTL(config.activateAfterIdle, "activateAfterIdle"),
6599
+ activateOnProviderChange: config.activateOnProviderChange ?? false,
6477
6600
  blockAfter: asyncBufferingDisabled ? void 0 : resolveBlockAfter(
6478
6601
  config.reflection?.blockAfter ?? (config.reflection?.bufferActivation ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.bufferActivation ? 1.2 : void 0),
6479
6602
  config.reflection?.observationTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.observationTokens
@@ -8370,6 +8493,8 @@ ${grouped}` : grouped;
8370
8493
  let activationTriggeredBy = "threshold";
8371
8494
  let activationLastActivityAt;
8372
8495
  let activateAfterIdleExpiredMs;
8496
+ let previousModel;
8497
+ let currentModel;
8373
8498
  if (opts.checkThreshold) {
8374
8499
  const thresholdMessages = opts.messages ?? await this.loadMessagesFromStorage(
8375
8500
  threadId,
@@ -8380,7 +8505,14 @@ ${grouped}` : grouped;
8380
8505
  const lastActivityAt = getLastActivityFromMessages(thresholdMessages);
8381
8506
  const ttlExpiredMs = activateAfterIdle !== void 0 && lastActivityAt !== void 0 ? Date.now() - lastActivityAt : void 0;
8382
8507
  const ttlExpired = ttlExpiredMs !== void 0 && activateAfterIdle !== void 0 && ttlExpiredMs >= activateAfterIdle;
8383
- if (ttlExpired) {
8508
+ const actorModel = getCurrentModel2(opts.currentModel);
8509
+ const lastModel = getLastModelFromMessages(thresholdMessages);
8510
+ const providerChanged = this.observationConfig.activateOnProviderChange === true && didProviderChange(actorModel, lastModel);
8511
+ if (providerChanged) {
8512
+ activationTriggeredBy = "provider_change";
8513
+ previousModel = lastModel;
8514
+ currentModel = actorModel;
8515
+ } else if (ttlExpired) {
8384
8516
  activationTriggeredBy = "ttl";
8385
8517
  activationLastActivityAt = lastActivityAt;
8386
8518
  activateAfterIdleExpiredMs = ttlExpiredMs;
@@ -8449,6 +8581,8 @@ ${grouped}` : grouped;
8449
8581
  triggeredBy: activationTriggeredBy,
8450
8582
  lastActivityAt: activationLastActivityAt,
8451
8583
  ttlExpiredMs: activateAfterIdleExpiredMs,
8584
+ previousModel,
8585
+ currentModel,
8452
8586
  config: this.getObservationMarkerConfig()
8453
8587
  });
8454
8588
  void opts.writer.custom(activationMarker).catch(() => {
@@ -8806,6 +8940,7 @@ var ObservationalMemoryProcessor = class {
8806
8940
  const observabilityContext = getOmObservabilityContext(args);
8807
8941
  state.__omObservabilityContext = observabilityContext;
8808
8942
  this.turn.observabilityContext = observabilityContext;
8943
+ this.turn.actorModelContext = actorModelContext;
8809
8944
  {
8810
8945
  const step = this.turn.step(stepNumber);
8811
8946
  let ctx;
@@ -8939,5 +9074,5 @@ function getObservationsAsOf(activeObservations, asOf) {
8939
9074
  }
8940
9075
 
8941
9076
  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 };
8942
- //# sourceMappingURL=chunk-HB6AYAFD.js.map
8943
- //# sourceMappingURL=chunk-HB6AYAFD.js.map
9077
+ //# sourceMappingURL=chunk-MGHUIRKN.js.map
9078
+ //# sourceMappingURL=chunk-MGHUIRKN.js.map