@mastra/memory 1.15.1 → 1.16.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 (34) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/{chunk-3TU4GGH3.cjs → chunk-3NECGYWZ.cjs} +117 -16
  3. package/dist/chunk-3NECGYWZ.cjs.map +1 -0
  4. package/dist/{chunk-7NCBGOHT.js → chunk-HB6AYAFD.js} +117 -16
  5. package/dist/chunk-HB6AYAFD.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 +23 -7
  9. package/dist/docs/references/reference-memory-observational-memory.md +2 -0
  10. package/dist/index.cjs +15 -14
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.ts +1 -0
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +6 -5
  15. package/dist/index.js.map +1 -1
  16. package/dist/{observational-memory-4TDIBXK6.js → observational-memory-WWAB2MMI.js} +3 -3
  17. package/dist/{observational-memory-4TDIBXK6.js.map → observational-memory-WWAB2MMI.js.map} +1 -1
  18. package/dist/{observational-memory-GH6IRH6E.cjs → observational-memory-X4N2R4CA.cjs} +26 -26
  19. package/dist/{observational-memory-GH6IRH6E.cjs.map → observational-memory-X4N2R4CA.cjs.map} +1 -1
  20. package/dist/processors/index.cjs +24 -24
  21. package/dist/processors/index.js +1 -1
  22. package/dist/processors/observational-memory/markers.d.ts +3 -0
  23. package/dist/processors/observational-memory/markers.d.ts.map +1 -1
  24. package/dist/processors/observational-memory/observation-turn/step.d.ts.map +1 -1
  25. package/dist/processors/observational-memory/observational-memory.d.ts +6 -0
  26. package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
  27. package/dist/processors/observational-memory/processor.d.ts.map +1 -1
  28. package/dist/processors/observational-memory/reflector-runner.d.ts +1 -0
  29. package/dist/processors/observational-memory/reflector-runner.d.ts.map +1 -1
  30. package/dist/processors/observational-memory/types.d.ts +19 -0
  31. package/dist/processors/observational-memory/types.d.ts.map +1 -1
  32. package/package.json +6 -6
  33. package/dist/chunk-3TU4GGH3.cjs.map +0 -1
  34. package/dist/chunk-7NCBGOHT.js.map +0 -1
@@ -484,7 +484,10 @@ function createActivationMarker(params) {
484
484
  threadId: params.threadId,
485
485
  generationCount: params.generationCount,
486
486
  config: params.config,
487
- observations: params.observations
487
+ observations: params.observations,
488
+ triggeredBy: params.triggeredBy,
489
+ lastActivityAt: params.lastActivityAt,
490
+ ttlExpiredMs: params.ttlExpiredMs
488
491
  }
489
492
  };
490
493
  }
@@ -2003,7 +2006,8 @@ var ObservationStep = class {
2003
2006
  threadId,
2004
2007
  writer: this.turn.writer,
2005
2008
  requestContext: this.turn.requestContext,
2006
- observabilityContext: this.turn.observabilityContext
2009
+ observabilityContext: this.turn.observabilityContext,
2010
+ lastActivityAt: getLastActivityFromMessages(messageList.get.all.db())
2007
2011
  });
2008
2012
  await this.turn.refreshRecord();
2009
2013
  if (this.turn.record.generationCount > preReflectGeneration) {
@@ -2179,7 +2183,8 @@ var ObservationStep = class {
2179
2183
  writer: this.turn.writer,
2180
2184
  messageList,
2181
2185
  requestContext: this.turn.requestContext,
2182
- observabilityContext: this.turn.observabilityContext
2186
+ observabilityContext: this.turn.observabilityContext,
2187
+ lastActivityAt: getLastActivityFromMessages(messageList.get.all.db())
2183
2188
  });
2184
2189
  return {
2185
2190
  succeeded: true,
@@ -4134,7 +4139,8 @@ var ReflectorRunner = class {
4134
4139
  observationTokens: getMaxThreshold(
4135
4140
  record ? this.getEffectiveReflectionTokens(record) : this.reflectionConfig.observationTokens
4136
4141
  ),
4137
- scope: this.scope
4142
+ scope: this.scope,
4143
+ activateAfterIdle: this.reflectionConfig.activateAfterIdle
4138
4144
  };
4139
4145
  }
4140
4146
  /**
@@ -4420,7 +4426,7 @@ var ReflectorRunner = class {
4420
4426
  * Try to activate buffered reflection when threshold is reached.
4421
4427
  * Returns true if activation succeeded.
4422
4428
  */
4423
- async tryActivateBufferedReflection(record, lockKey, writer, messageList) {
4429
+ async tryActivateBufferedReflection(record, lockKey, writer, messageList, activationMetadata) {
4424
4430
  const bufferKey = this.buffering.getReflectionBufferKey(lockKey);
4425
4431
  const asyncOp = BufferingCoordinator.asyncBufferingOps.get(bufferKey);
4426
4432
  if (asyncOp) {
@@ -4480,6 +4486,9 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
4480
4486
  threadId: freshRecord.threadId ?? "",
4481
4487
  generationCount: afterRecord?.generationCount ?? freshRecord.generationCount ?? 0,
4482
4488
  observations: afterRecord?.activeObservations,
4489
+ triggeredBy: activationMetadata?.triggeredBy,
4490
+ lastActivityAt: activationMetadata?.lastActivityAt,
4491
+ ttlExpiredMs: activationMetadata?.ttlExpiredMs,
4483
4492
  config: this.getObservationMarkerConfig(freshRecord)
4484
4493
  });
4485
4494
  void writer.custom(activationMarker).catch(() => {
@@ -4508,7 +4517,9 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
4508
4517
  messageList,
4509
4518
  reflectionHooks,
4510
4519
  requestContext,
4511
- observabilityContext
4520
+ observabilityContext,
4521
+ lastActivityAt,
4522
+ threadId: requestedThreadId
4512
4523
  } = opts;
4513
4524
  const lockKey = this.buffering.getLockKey(record.threadId, record.resourceId);
4514
4525
  const reflectThreshold = getMaxThreshold(this.getEffectiveReflectionTokens(record));
@@ -4540,9 +4551,17 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
4540
4551
  );
4541
4552
  }
4542
4553
  }
4543
- if (observationTokens < reflectThreshold) {
4554
+ const activateAfterIdle = this.reflectionConfig.activateAfterIdle;
4555
+ const ttlExpiredMs = activateAfterIdle !== void 0 && lastActivityAt !== void 0 ? Date.now() - lastActivityAt : void 0;
4556
+ const ttlExpired = ttlExpiredMs !== void 0 && activateAfterIdle !== void 0 && ttlExpiredMs >= activateAfterIdle;
4557
+ if (observationTokens < reflectThreshold && !ttlExpired) {
4544
4558
  return;
4545
4559
  }
4560
+ const activationMetadata = {
4561
+ triggeredBy: ttlExpired ? "ttl" : "threshold",
4562
+ lastActivityAt: ttlExpired ? lastActivityAt : void 0,
4563
+ ttlExpiredMs: ttlExpired ? ttlExpiredMs : void 0
4564
+ };
4546
4565
  if (record.isReflecting) {
4547
4566
  if (isOpActiveInProcess(record.id, "reflecting")) {
4548
4567
  omDebug(`[OM:reflect] isReflecting=true and active in this process, skipping`);
@@ -4552,7 +4571,13 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
4552
4571
  await this.storage.setReflectingFlag(record.id, false);
4553
4572
  }
4554
4573
  if (this.buffering.isAsyncReflectionEnabled()) {
4555
- const activationSuccess = await this.tryActivateBufferedReflection(record, lockKey, writer, messageList);
4574
+ const activationSuccess = await this.tryActivateBufferedReflection(
4575
+ record,
4576
+ lockKey,
4577
+ writer,
4578
+ messageList,
4579
+ activationMetadata
4580
+ );
4556
4581
  if (activationSuccess) {
4557
4582
  return;
4558
4583
  }
@@ -4581,7 +4606,7 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
4581
4606
  registerOp(record.id, "reflecting");
4582
4607
  const cycleId = crypto.randomUUID();
4583
4608
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
4584
- const threadId = opts.threadId ?? "unknown";
4609
+ const threadId = requestedThreadId ?? "unknown";
4585
4610
  if (writer) {
4586
4611
  const startMarker = createObservationStartMarker({
4587
4612
  cycleId,
@@ -6231,6 +6256,58 @@ function buildMessageRange(messages) {
6231
6256
  const last = [...messages].reverse().find(messageHasVisibleContent) ?? messages[messages.length - 1];
6232
6257
  return `${first.id}:${last.id}`;
6233
6258
  }
6259
+ function getLastActivityFromMessages(messages) {
6260
+ if (!messages) return void 0;
6261
+ for (let i = messages.length - 1; i >= 0; i--) {
6262
+ const message = messages[i];
6263
+ if (!message || message.role !== "assistant") {
6264
+ continue;
6265
+ }
6266
+ if (!message.content || typeof message.content === "string") {
6267
+ return message.createdAt ? new Date(message.createdAt).getTime() : void 0;
6268
+ }
6269
+ for (let j = message.content.parts.length - 1; j >= 0; j--) {
6270
+ const part = message.content.parts[j];
6271
+ if (!part || part.type?.startsWith("data-")) {
6272
+ continue;
6273
+ }
6274
+ if (part.createdAt !== void 0) {
6275
+ return part.createdAt;
6276
+ }
6277
+ }
6278
+ return message.createdAt ? new Date(message.createdAt).getTime() : void 0;
6279
+ }
6280
+ return void 0;
6281
+ }
6282
+ function parseActivationTTL(value, fieldPath) {
6283
+ if (value === void 0) {
6284
+ return void 0;
6285
+ }
6286
+ if (typeof value === "number") {
6287
+ if (!Number.isFinite(value) || value < 0) {
6288
+ throw new Error(`${fieldPath} must be a non-negative number of milliseconds or a duration string like "5m".`);
6289
+ }
6290
+ return value;
6291
+ }
6292
+ const trimmed = value.trim();
6293
+ const match = trimmed.match(
6294
+ /^(\d+(?:\.\d+)?)\s*(ms|msec|msecs|millisecond|milliseconds|s|sec|secs|second|seconds|m|min|mins|minute|minutes|h|hr|hrs|hour|hours)$/i
6295
+ );
6296
+ if (!match) {
6297
+ throw new Error(
6298
+ `${fieldPath} must be a non-negative number of milliseconds or a duration string like "5m" or "1hr".`
6299
+ );
6300
+ }
6301
+ const rawAmount = match[1];
6302
+ const rawUnit = match[2];
6303
+ const amount = Number(rawAmount);
6304
+ const unit = rawUnit.toLowerCase();
6305
+ if (!Number.isFinite(amount) || amount < 0) {
6306
+ throw new Error(`${fieldPath} must be a non-negative number of milliseconds or a duration string like "5m".`);
6307
+ }
6308
+ const multiplier = unit === "ms" || unit === "msec" || unit === "msecs" || unit === "millisecond" || unit === "milliseconds" ? 1 : unit === "s" || unit === "sec" || unit === "secs" || unit === "second" || unit === "seconds" ? 1e3 : unit === "m" || unit === "min" || unit === "mins" || unit === "minute" || unit === "minutes" ? 6e4 : 36e5;
6309
+ return amount * multiplier;
6310
+ }
6234
6311
  var ObservationalMemory = class _ObservationalMemory {
6235
6312
  storage;
6236
6313
  tokenCounter;
@@ -6377,6 +6454,7 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
6377
6454
  config.observation?.messageTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.messageTokens
6378
6455
  ),
6379
6456
  bufferActivation: asyncBufferingDisabled ? void 0 : config.observation?.bufferActivation ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.bufferActivation,
6457
+ activateAfterIdle: parseActivationTTL(config.activateAfterIdle, "activateAfterIdle"),
6380
6458
  blockAfter: asyncBufferingDisabled ? void 0 : resolveBlockAfter(
6381
6459
  config.observation?.blockAfter ?? (config.observation?.bufferTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.bufferTokens ? 1.2 : void 0),
6382
6460
  config.observation?.messageTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.messageTokens
@@ -6395,6 +6473,7 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
6395
6473
  },
6396
6474
  providerOptions: config.reflection?.providerOptions ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.providerOptions,
6397
6475
  bufferActivation: asyncBufferingDisabled ? void 0 : config?.reflection?.bufferActivation ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.bufferActivation,
6476
+ activateAfterIdle: parseActivationTTL(config.activateAfterIdle, "activateAfterIdle"),
6398
6477
  blockAfter: asyncBufferingDisabled ? void 0 : resolveBlockAfter(
6399
6478
  config.reflection?.blockAfter ?? (config.reflection?.bufferActivation ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.bufferActivation ? 1.2 : void 0),
6400
6479
  config.reflection?.observationTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.observationTokens
@@ -6789,7 +6868,8 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
6789
6868
  return {
6790
6869
  messageTokens: getMaxThreshold(this.observationConfig.messageTokens),
6791
6870
  observationTokens: getMaxThreshold(this.reflectionConfig.observationTokens),
6792
- scope: this.scope
6871
+ scope: this.scope,
6872
+ activateAfterIdle: this.observationConfig.activateAfterIdle
6793
6873
  };
6794
6874
  }
6795
6875
  /**
@@ -8027,7 +8107,7 @@ ${grouped}` : grouped;
8027
8107
  await BufferingCoordinator.awaitBuffering(threadId, resourceId ?? null, this.scope);
8028
8108
  const preStatus = await this.getStatus({ threadId, resourceId, messages });
8029
8109
  if (preStatus.canActivate) {
8030
- const actResult = await this.activate({ threadId, resourceId });
8110
+ const actResult = await this.activate({ threadId, resourceId, messages });
8031
8111
  activated = actResult.activated;
8032
8112
  }
8033
8113
  const postStatus = await this.getStatus({ threadId, resourceId, messages });
@@ -8287,10 +8367,28 @@ ${grouped}` : grouped;
8287
8367
  if (!chunks.length) {
8288
8368
  return { activated: false, record };
8289
8369
  }
8370
+ let activationTriggeredBy = "threshold";
8371
+ let activationLastActivityAt;
8372
+ let activateAfterIdleExpiredMs;
8290
8373
  if (opts.checkThreshold) {
8291
- const status = await this.getStatus({ threadId, resourceId, messages: opts.messages });
8292
- if (status.pendingTokens < status.threshold) {
8293
- return { activated: false, record };
8374
+ const thresholdMessages = opts.messages ?? await this.loadMessagesFromStorage(
8375
+ threadId,
8376
+ resourceId,
8377
+ record.lastObservedAt ? new Date(record.lastObservedAt) : void 0
8378
+ );
8379
+ const activateAfterIdle = this.observationConfig.activateAfterIdle;
8380
+ const lastActivityAt = getLastActivityFromMessages(thresholdMessages);
8381
+ const ttlExpiredMs = activateAfterIdle !== void 0 && lastActivityAt !== void 0 ? Date.now() - lastActivityAt : void 0;
8382
+ const ttlExpired = ttlExpiredMs !== void 0 && activateAfterIdle !== void 0 && ttlExpiredMs >= activateAfterIdle;
8383
+ if (ttlExpired) {
8384
+ activationTriggeredBy = "ttl";
8385
+ activationLastActivityAt = lastActivityAt;
8386
+ activateAfterIdleExpiredMs = ttlExpiredMs;
8387
+ } else {
8388
+ const status = await this.getStatus({ threadId, resourceId, messages: thresholdMessages });
8389
+ if (status.pendingTokens < status.threshold) {
8390
+ return { activated: false, record };
8391
+ }
8294
8392
  }
8295
8393
  }
8296
8394
  if (record.isBufferingObservation) {
@@ -8348,6 +8446,9 @@ ${grouped}` : grouped;
8348
8446
  threadId: postSwapRecord.threadId ?? record.threadId ?? "",
8349
8447
  generationCount: postSwapRecord.generationCount ?? 0,
8350
8448
  observations: chunkData?.observations ?? activationResult.observations,
8449
+ triggeredBy: activationTriggeredBy,
8450
+ lastActivityAt: activationLastActivityAt,
8451
+ ttlExpiredMs: activateAfterIdleExpiredMs,
8351
8452
  config: this.getObservationMarkerConfig()
8352
8453
  });
8353
8454
  void opts.writer.custom(activationMarker).catch(() => {
@@ -8838,5 +8939,5 @@ function getObservationsAsOf(activeObservations, asOf) {
8838
8939
  }
8839
8940
 
8840
8941
  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 };
8841
- //# sourceMappingURL=chunk-7NCBGOHT.js.map
8842
- //# sourceMappingURL=chunk-7NCBGOHT.js.map
8942
+ //# sourceMappingURL=chunk-HB6AYAFD.js.map
8943
+ //# sourceMappingURL=chunk-HB6AYAFD.js.map