@mastra/memory 1.19.0 → 1.20.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 (40) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/{chunk-NZXH5WER.js → chunk-G72RLVRT.js} +70 -40
  3. package/dist/chunk-G72RLVRT.js.map +1 -0
  4. package/dist/{chunk-5IJQOXJM.cjs → chunk-PNKMNTE6.cjs} +69 -39
  5. package/dist/chunk-PNKMNTE6.cjs.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-multi-user-threads.md +1 -1
  9. package/dist/docs/references/docs-memory-observational-memory.md +2 -2
  10. package/dist/docs/references/docs-memory-storage.md +1 -1
  11. package/dist/docs/references/reference-memory-observational-memory.md +1 -1
  12. package/dist/docs/references/reference-storage-dsql.md +1 -1
  13. package/dist/docs/references/reference-storage-redis.md +1 -1
  14. package/dist/index.cjs +15 -14
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +6 -5
  19. package/dist/index.js.map +1 -1
  20. package/dist/{observational-memory-V2APY3TO.cjs → observational-memory-25PDEXBJ.cjs} +26 -26
  21. package/dist/{observational-memory-V2APY3TO.cjs.map → observational-memory-25PDEXBJ.cjs.map} +1 -1
  22. package/dist/{observational-memory-KFKHBTCB.js → observational-memory-FBSRD6QN.js} +3 -3
  23. package/dist/{observational-memory-KFKHBTCB.js.map → observational-memory-FBSRD6QN.js.map} +1 -1
  24. package/dist/processors/index.cjs +24 -24
  25. package/dist/processors/index.js +1 -1
  26. package/dist/processors/observational-memory/message-utils.d.ts +1 -0
  27. package/dist/processors/observational-memory/message-utils.d.ts.map +1 -1
  28. package/dist/processors/observational-memory/observation-strategies/async-buffer.d.ts.map +1 -1
  29. package/dist/processors/observational-memory/observation-strategies/sync.d.ts.map +1 -1
  30. package/dist/processors/observational-memory/observation-turn/step.d.ts.map +1 -1
  31. package/dist/processors/observational-memory/observer-runner.d.ts +11 -0
  32. package/dist/processors/observational-memory/observer-runner.d.ts.map +1 -1
  33. package/dist/processors/observational-memory/processor.d.ts.map +1 -1
  34. package/dist/processors/observational-memory/temporal-markers.d.ts +1 -1
  35. package/dist/processors/observational-memory/temporal-markers.d.ts.map +1 -1
  36. package/dist/processors/observational-memory/types.d.ts +7 -3
  37. package/dist/processors/observational-memory/types.d.ts.map +1 -1
  38. package/package.json +3 -3
  39. package/dist/chunk-5IJQOXJM.cjs.map +0 -1
  40. package/dist/chunk-NZXH5WER.js.map +0 -1
@@ -676,6 +676,7 @@ function filterObservedMessages(opts) {
676
676
  const { messageList, record } = opts;
677
677
  const allMessages = messageList.get.all.db();
678
678
  const useMarkerBoundaryPruning = opts.useMarkerBoundaryPruning ?? true;
679
+ const preserveMessageIds = opts.preserveMessageIds ?? /* @__PURE__ */ new Set();
679
680
  let markerMessageIndex = -1;
680
681
  let markerMessage = null;
681
682
  for (let i = allMessages.length - 1; i >= 0; i--) {
@@ -691,7 +692,7 @@ function filterObservedMessages(opts) {
691
692
  const messagesToRemove = [];
692
693
  for (let i = 0; i < markerMessageIndex; i++) {
693
694
  const msg = allMessages[i];
694
- if (msg?.id && msg.id !== "om-continuation") {
695
+ if (msg?.id && msg.id !== "om-continuation" && !preserveMessageIds.has(msg.id)) {
695
696
  messagesToRemove.push(msg.id);
696
697
  }
697
698
  }
@@ -710,7 +711,7 @@ function filterObservedMessages(opts) {
710
711
  const lastObservedAt = record.lastObservedAt;
711
712
  const messagesToRemove = [];
712
713
  for (const msg of allMessages) {
713
- if (!msg?.id || msg.id === "om-continuation") continue;
714
+ if (!msg?.id || msg.id === "om-continuation" || preserveMessageIds.has(msg.id)) continue;
714
715
  if (observedIds.has(msg.id)) {
715
716
  messagesToRemove.push(msg.id);
716
717
  continue;
@@ -2276,11 +2277,15 @@ var ObservationStep = class {
2276
2277
  });
2277
2278
  if (!didThresholdCleanup) {
2278
2279
  const fallbackCursor = this.turn.record.threadId ? memory.getThreadOMMetadata((await om.getStorage().getThreadById({ threadId: this.turn.record.threadId }))?.metadata)?.lastObservedMessageCursor : void 0;
2280
+ const pendingMessageIds = new Set(
2281
+ [...messageList.get.input.db(), ...messageList.get.response.db()].map((msg) => msg.id).filter(Boolean)
2282
+ );
2279
2283
  filterObservedMessages({
2280
2284
  messageList,
2281
2285
  record: this.turn.record,
2282
2286
  useMarkerBoundaryPruning: this.stepNumber === 0,
2283
- fallbackCursor
2287
+ fallbackCursor,
2288
+ preserveMessageIds: pendingMessageIds
2284
2289
  });
2285
2290
  }
2286
2291
  this._context = {
@@ -4108,6 +4113,41 @@ var ObserverRunner = class {
4108
4113
  }
4109
4114
  return agent$1;
4110
4115
  }
4116
+ /**
4117
+ * Extract a router-style model ID (`provider/model`) from a model config.
4118
+ * Handles strings, LanguageModel objects, and function-based models.
4119
+ */
4120
+ extractModelRouterId(model, requestContext) {
4121
+ if (typeof model === "string") return model;
4122
+ if (typeof model === "function") {
4123
+ if (!requestContext) return void 0;
4124
+ try {
4125
+ const resolved = model({ requestContext });
4126
+ if (resolved instanceof Promise) return void 0;
4127
+ return this.extractModelRouterId(resolved);
4128
+ } catch {
4129
+ return void 0;
4130
+ }
4131
+ }
4132
+ const obj = model;
4133
+ if (typeof obj.provider === "string" && typeof obj.modelId === "string") {
4134
+ return `${obj.provider}/${obj.modelId}`;
4135
+ }
4136
+ return void 0;
4137
+ }
4138
+ /**
4139
+ * Resolve the attachment filter for a given model. When set to `'auto'`,
4140
+ * the provider capabilities registry is consulted to decide whether the
4141
+ * model accepts multimodal input.
4142
+ */
4143
+ resolveAttachmentFilter(model, requestContext) {
4144
+ const raw = this.observationConfig.observeAttachments;
4145
+ if (raw !== "auto") return raw;
4146
+ const routerId = this.extractModelRouterId(model, requestContext);
4147
+ if (!routerId) return true;
4148
+ const supports = llm.modelSupportsAttachments(routerId);
4149
+ return supports ?? true;
4150
+ }
4111
4151
  async withAbortCheck(fn, abortSignal) {
4112
4152
  if (abortSignal?.aborted) {
4113
4153
  throw new Error("The operation was aborted.");
@@ -4125,6 +4165,7 @@ var ObserverRunner = class {
4125
4165
  const inputTokens = this.tokenCounter.countMessages(messagesToObserve);
4126
4166
  const resolvedModel = options?.model ? { model: options.model } : this.resolveModel(inputTokens);
4127
4167
  const agent = this.createAgent(resolvedModel.model);
4168
+ const attachmentFilter = this.resolveAttachmentFilter(resolvedModel.model, options?.requestContext);
4128
4169
  const observerMessages = [
4129
4170
  {
4130
4171
  role: "user",
@@ -4134,7 +4175,7 @@ var ObserverRunner = class {
4134
4175
  })
4135
4176
  },
4136
4177
  buildObserverHistoryMessage(messagesToObserve, {
4137
- attachmentFilter: this.observationConfig.observeAttachments
4178
+ attachmentFilter
4138
4179
  })
4139
4180
  ];
4140
4181
  const doGenerate = async () => {
@@ -4221,6 +4262,7 @@ var ObserverRunner = class {
4221
4262
  );
4222
4263
  const resolvedModel = model ? { model } : this.resolveModel(inputTokens);
4223
4264
  const agent = this.createAgent(resolvedModel.model, true);
4265
+ const multiThreadAttachmentFilter = this.resolveAttachmentFilter(resolvedModel.model, requestContext);
4224
4266
  const observerMessages = [
4225
4267
  {
4226
4268
  role: "user",
@@ -4233,7 +4275,7 @@ var ObserverRunner = class {
4233
4275
  )
4234
4276
  },
4235
4277
  buildMultiThreadObserverHistoryMessage(messagesByThread, threadOrder, {
4236
- attachmentFilter: this.observationConfig.observeAttachments
4278
+ attachmentFilter: multiThreadAttachmentFilter
4237
4279
  })
4238
4280
  ];
4239
4281
  for (const msgs of messagesByThread.values()) {
@@ -9473,6 +9515,16 @@ function getTemporalGapReminderMetadata(message, gapText, gapMs, timestamp) {
9473
9515
  }
9474
9516
  };
9475
9517
  }
9518
+ function getTemporalGapReminderAttributes(message, gapText, gapMs, timestamp) {
9519
+ return {
9520
+ type: TEMPORAL_GAP_REMINDER_TYPE,
9521
+ gapText,
9522
+ gapMs,
9523
+ timestamp: formatTemporalTimestamp(new Date(timestamp)),
9524
+ timestampMs: timestamp,
9525
+ precedesMessageId: message.id
9526
+ };
9527
+ }
9476
9528
  function isTemporalGapMarkerForMessage(message, targetMessageId) {
9477
9529
  if (!isTemporalGapMarker(message)) {
9478
9530
  return false;
@@ -9483,29 +9535,9 @@ function isTemporalGapMarkerForMessage(message, targetMessageId) {
9483
9535
  }
9484
9536
  return metadata?.systemReminder?.type === TEMPORAL_GAP_REMINDER_TYPE && metadata.systemReminder.precedesMessageId === targetMessageId;
9485
9537
  }
9486
- function createTemporalGapMarker(message, gapText, gapMs, timestamp) {
9487
- const metadata = getTemporalGapReminderMetadata(message, gapText, gapMs, timestamp);
9488
- return {
9489
- id: `__temporal_gap_${crypto.randomUUID()}`,
9490
- role: "user",
9491
- createdAt: new Date(timestamp - 1),
9492
- threadId: message.threadId,
9493
- resourceId: message.resourceId,
9494
- content: {
9495
- format: 2,
9496
- parts: [
9497
- {
9498
- type: "text",
9499
- text: `<system-reminder type="${TEMPORAL_GAP_REMINDER_TYPE}" precedesMessageId="${message.id}">${getTemporalGapReminderText(gapText, timestamp)}</system-reminder>`
9500
- }
9501
- ],
9502
- metadata
9503
- }
9504
- };
9505
- }
9506
9538
  async function insertTemporalGapMarkers({
9507
9539
  messageList,
9508
- writer
9540
+ sendSignal
9509
9541
  }) {
9510
9542
  const inputMessages = messageList.get.input.db().filter((message) => Boolean(message));
9511
9543
  const latestInputMessage = inputMessages.at(-1);
@@ -9537,17 +9569,15 @@ async function insertTemporalGapMarkers({
9537
9569
  if (!gapText) {
9538
9570
  return;
9539
9571
  }
9540
- const reminderMetadata = getTemporalGapReminderMetadata(latestInputMessage, gapText, gapMs, timestamp);
9541
- await writer?.custom({
9542
- type: "data-system-reminder",
9543
- data: {
9544
- message: getTemporalGapReminderText(gapText, timestamp),
9545
- ...reminderMetadata
9546
- },
9547
- transient: true
9572
+ await sendSignal?.({
9573
+ id: `__temporal_gap_${crypto.randomUUID()}`,
9574
+ type: "system-reminder",
9575
+ contents: getTemporalGapReminderText(gapText, timestamp),
9576
+ createdAt: new Date(timestamp - 1),
9577
+ acceptedAt: new Date(timestamp),
9578
+ attributes: getTemporalGapReminderAttributes(latestInputMessage, gapText, gapMs, timestamp),
9579
+ metadata: getTemporalGapReminderMetadata(latestInputMessage, gapText, gapMs, timestamp)
9548
9580
  });
9549
- const marker = createTemporalGapMarker(latestInputMessage, gapText, gapMs, timestamp);
9550
- messageList.add(marker, "input");
9551
9581
  }
9552
9582
 
9553
9583
  // src/processors/observational-memory/processor.ts
@@ -9696,7 +9726,7 @@ var ObservationalMemoryProcessor = class {
9696
9726
  this.turn.requestContext = requestContext;
9697
9727
  await this.turn.start(this.memory);
9698
9728
  if (stepNumber === 0 && this.temporalMarkers) {
9699
- await insertTemporalGapMarkers({ messageList, writer });
9729
+ await insertTemporalGapMarkers({ messageList, sendSignal: args.sendSignal });
9700
9730
  }
9701
9731
  state.__omTurn = this.turn;
9702
9732
  }
@@ -9853,5 +9883,5 @@ exports.stripEphemeralAnchorIds = stripEphemeralAnchorIds;
9853
9883
  exports.stripObservationGroups = stripObservationGroups;
9854
9884
  exports.truncateStringByTokens = truncateStringByTokens;
9855
9885
  exports.wrapInObservationGroup = wrapInObservationGroup;
9856
- //# sourceMappingURL=chunk-5IJQOXJM.cjs.map
9857
- //# sourceMappingURL=chunk-5IJQOXJM.cjs.map
9886
+ //# sourceMappingURL=chunk-PNKMNTE6.cjs.map
9887
+ //# sourceMappingURL=chunk-PNKMNTE6.cjs.map