@mastra/memory 1.10.1-alpha.2 → 1.10.1-alpha.3

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 (29) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/{chunk-NS47X3OB.cjs → chunk-DTAZSLVU.cjs} +214 -79
  3. package/dist/chunk-DTAZSLVU.cjs.map +1 -0
  4. package/dist/{chunk-2QSOQQPM.js → chunk-SKRONGCV.js} +214 -79
  5. package/dist/chunk-SKRONGCV.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/index.cjs +11 -11
  9. package/dist/index.js +4 -4
  10. package/dist/{observational-memory-WMCWT577.js → observational-memory-UGDENJPE.js} +3 -3
  11. package/dist/{observational-memory-WMCWT577.js.map → observational-memory-UGDENJPE.js.map} +1 -1
  12. package/dist/{observational-memory-I5UTOG63.cjs → observational-memory-XIZTJN3S.cjs} +26 -26
  13. package/dist/{observational-memory-I5UTOG63.cjs.map → observational-memory-XIZTJN3S.cjs.map} +1 -1
  14. package/dist/processors/index.cjs +24 -24
  15. package/dist/processors/index.js +1 -1
  16. package/dist/processors/observational-memory/observation-turn/index.d.ts +1 -1
  17. package/dist/processors/observational-memory/observation-turn/index.d.ts.map +1 -1
  18. package/dist/processors/observational-memory/observation-turn/step.d.ts.map +1 -1
  19. package/dist/processors/observational-memory/observation-turn/turn.d.ts +15 -7
  20. package/dist/processors/observational-memory/observation-turn/turn.d.ts.map +1 -1
  21. package/dist/processors/observational-memory/observation-turn/types.d.ts +4 -0
  22. package/dist/processors/observational-memory/observation-turn/types.d.ts.map +1 -1
  23. package/dist/processors/observational-memory/observational-memory.d.ts +2 -0
  24. package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
  25. package/dist/processors/observational-memory/processor.d.ts.map +1 -1
  26. package/dist/processors/observational-memory/repro-capture.d.ts.map +1 -1
  27. package/package.json +4 -4
  28. package/dist/chunk-2QSOQQPM.js.map +0 -1
  29. package/dist/chunk-NS47X3OB.cjs.map +0 -1
@@ -11,6 +11,7 @@ import { estimateTokenCount } from 'tokenx';
11
11
  import { Agent } from '@mastra/core/agent';
12
12
  import { AsyncLocalStorage } from 'async_hooks';
13
13
  import imageSize from 'image-size';
14
+ import { inspect } from 'util';
14
15
 
15
16
  var OM_DEBUG_LOG = process.env.OM_DEBUG ? join(process.cwd(), "om-debug.log") : null;
16
17
  function omDebug(msg) {
@@ -1939,7 +1940,17 @@ var ObservationStep = class {
1939
1940
  writer: this.turn.writer,
1940
1941
  requestContext: this.turn.requestContext,
1941
1942
  beforeBuffer: async (candidates) => {
1943
+ if (candidates.length === 0) {
1944
+ return;
1945
+ }
1942
1946
  om.sealMessagesForBuffering(candidates);
1947
+ try {
1948
+ await this.turn.hooks?.onBufferChunkSealed?.();
1949
+ } catch (error) {
1950
+ omDebug(
1951
+ `[OM:buffer] onBufferChunkSealed hook failed: ${error instanceof Error ? error.message : String(error)}`
1952
+ );
1953
+ }
1943
1954
  if (this.turn.memory) {
1944
1955
  await this.turn.memory.persistMessages(candidates);
1945
1956
  }
@@ -2086,12 +2097,6 @@ var ObservationStep = class {
2086
2097
 
2087
2098
  // src/processors/observational-memory/observation-turn/turn.ts
2088
2099
  var ObservationTurn = class {
2089
- constructor(om, threadId, resourceId, messageList) {
2090
- this.om = om;
2091
- this.threadId = threadId;
2092
- this.resourceId = resourceId;
2093
- this.messageList = messageList;
2094
- }
2095
2100
  _record;
2096
2101
  _context;
2097
2102
  _currentStep;
@@ -2105,6 +2110,19 @@ var ObservationTurn = class {
2105
2110
  writer;
2106
2111
  /** Optional request context for observation calls. */
2107
2112
  requestContext;
2113
+ /** Optional processor-provided hooks for turn/step lifecycle integration. */
2114
+ hooks;
2115
+ constructor(opts) {
2116
+ this.om = opts.om;
2117
+ this.threadId = opts.threadId;
2118
+ this.resourceId = opts.resourceId;
2119
+ this.messageList = opts.messageList;
2120
+ this.hooks = opts.hooks;
2121
+ }
2122
+ om;
2123
+ threadId;
2124
+ resourceId;
2125
+ messageList;
2108
2126
  /** The current cached record. Refreshed after mutations (activate/observe/reflect). */
2109
2127
  get record() {
2110
2128
  if (!this._record) throw new Error("Turn not started \u2014 call start() first");
@@ -2167,7 +2185,7 @@ var ObservationTurn = class {
2167
2185
  return this._currentStep;
2168
2186
  }
2169
2187
  /**
2170
- * Finalize the turn: save any remaining messages, await in-flight buffering, return final state.
2188
+ * Finalize the turn: save any remaining messages and return the latest record state.
2171
2189
  */
2172
2190
  async end() {
2173
2191
  if (this._ended) throw new Error("Turn already ended");
@@ -2178,22 +2196,6 @@ var ObservationTurn = class {
2178
2196
  if (unsavedMessages.length > 0) {
2179
2197
  await this.om.persistMessages(unsavedMessages, this.threadId, this.resourceId);
2180
2198
  }
2181
- await this.om.waitForBuffering(this.threadId, this.resourceId);
2182
- const status = await this.om.getStatus({
2183
- threadId: this.threadId,
2184
- resourceId: this.resourceId,
2185
- messages: this.messageList.get.all.db()
2186
- });
2187
- if (status.shouldObserve) {
2188
- await this.om.observe({
2189
- threadId: this.threadId,
2190
- resourceId: this.resourceId,
2191
- messages: this.messageList.get.all.db(),
2192
- requestContext: this.requestContext,
2193
- writer: this.writer
2194
- });
2195
- }
2196
- await this.refreshRecord();
2197
2199
  return { record: this._record };
2198
2200
  }
2199
2201
  /**
@@ -7716,7 +7718,13 @@ ${grouped}` : grouped;
7716
7718
  * ```
7717
7719
  */
7718
7720
  beginTurn(opts) {
7719
- return new ObservationTurn(this, opts.threadId, opts.resourceId, opts.messageList);
7721
+ return new ObservationTurn({
7722
+ om: this,
7723
+ threadId: opts.threadId,
7724
+ resourceId: opts.resourceId,
7725
+ messageList: opts.messageList,
7726
+ hooks: opts.hooks
7727
+ });
7720
7728
  }
7721
7729
  };
7722
7730
  var OM_REPRO_CAPTURE_DIR = process.env.OM_REPRO_CAPTURE_DIR ?? ".mastra-om-repro";
@@ -7732,6 +7740,7 @@ function safeCaptureJson(value) {
7732
7740
  JSON.stringify(value, (_key, current) => {
7733
7741
  if (typeof current === "bigint") return current.toString();
7734
7742
  if (typeof current === "function") return "[function]";
7743
+ if (typeof current === "symbol") return current.toString();
7735
7744
  if (current instanceof Error) return { name: current.name, message: current.message, stack: current.stack };
7736
7745
  if (current instanceof Set) return { __type: "Set", values: Array.from(current.values()) };
7737
7746
  if (current instanceof Map) return { __type: "Map", entries: Array.from(current.entries()) };
@@ -7739,6 +7748,87 @@ function safeCaptureJson(value) {
7739
7748
  })
7740
7749
  );
7741
7750
  }
7751
+ function safeCaptureJsonOrError(value) {
7752
+ try {
7753
+ return { ok: true, value: safeCaptureJson(value) };
7754
+ } catch (error) {
7755
+ return {
7756
+ ok: false,
7757
+ error: safeCaptureJson({
7758
+ message: error instanceof Error ? error.message : String(error),
7759
+ stack: error instanceof Error ? error.stack : void 0,
7760
+ inspected: inspect(value, { depth: 3, maxArrayLength: 20, breakLength: 120 })
7761
+ })
7762
+ };
7763
+ }
7764
+ }
7765
+ function formatCaptureDate(value) {
7766
+ if (!value) return void 0;
7767
+ if (value instanceof Date) return value.toISOString();
7768
+ try {
7769
+ return new Date(value).toISOString();
7770
+ } catch {
7771
+ return void 0;
7772
+ }
7773
+ }
7774
+ function summarizeOmTurn(value) {
7775
+ if (!value || typeof value !== "object") {
7776
+ return value;
7777
+ }
7778
+ const turn = value;
7779
+ return {
7780
+ __type: "ObservationTurn",
7781
+ threadId: turn.threadId,
7782
+ resourceId: turn.resourceId,
7783
+ started: turn._started,
7784
+ ended: turn._ended,
7785
+ generationCountAtStart: turn._generationCountAtStart,
7786
+ record: turn._record ? {
7787
+ id: turn._record.id,
7788
+ scope: turn._record.scope,
7789
+ threadId: turn._record.threadId,
7790
+ resourceId: turn._record.resourceId,
7791
+ createdAt: formatCaptureDate(turn._record.createdAt),
7792
+ updatedAt: formatCaptureDate(turn._record.updatedAt),
7793
+ lastObservedAt: formatCaptureDate(turn._record.lastObservedAt),
7794
+ generationCount: turn._record.generationCount,
7795
+ observationTokenCount: turn._record.observationTokenCount,
7796
+ pendingMessageTokens: turn._record.pendingMessageTokens,
7797
+ isBufferingObservation: turn._record.isBufferingObservation,
7798
+ isBufferingReflection: turn._record.isBufferingReflection
7799
+ } : void 0,
7800
+ context: turn._context ? {
7801
+ messageCount: Array.isArray(turn._context.messages) ? turn._context.messages.length : void 0,
7802
+ hasSystemMessage: Array.isArray(turn._context.systemMessage) ? turn._context.systemMessage.length > 0 : Boolean(turn._context.systemMessage),
7803
+ continuationId: turn._context.continuation?.id,
7804
+ hasOtherThreadsContext: Boolean(turn._context.otherThreadsContext),
7805
+ recordId: turn._context.record?.id
7806
+ } : void 0,
7807
+ currentStep: turn._currentStep ? {
7808
+ stepNumber: turn._currentStep.stepNumber,
7809
+ prepared: turn._currentStep._prepared,
7810
+ context: turn._currentStep._context ? {
7811
+ activated: turn._currentStep._context.activated,
7812
+ observed: turn._currentStep._context.observed,
7813
+ buffered: turn._currentStep._context.buffered,
7814
+ reflected: turn._currentStep._context.reflected,
7815
+ didThresholdCleanup: turn._currentStep._context.didThresholdCleanup,
7816
+ messageCount: Array.isArray(turn._currentStep._context.messages) ? turn._currentStep._context.messages.length : void 0,
7817
+ systemMessageCount: Array.isArray(turn._currentStep._context.systemMessage) ? turn._currentStep._context.systemMessage.length : void 0
7818
+ } : void 0
7819
+ } : void 0
7820
+ };
7821
+ }
7822
+ function sanitizeCaptureState(rawState) {
7823
+ return Object.fromEntries(
7824
+ Object.entries(rawState).map(([key, value]) => {
7825
+ if (key === "__omTurn") {
7826
+ return [key, summarizeOmTurn(value)];
7827
+ }
7828
+ return [key, value];
7829
+ })
7830
+ );
7831
+ }
7742
7832
  function buildReproMessageFingerprint(message) {
7743
7833
  const createdAt = message.createdAt instanceof Date ? message.createdAt.toISOString() : message.createdAt ? new Date(message.createdAt).toISOString() : "";
7744
7834
  return JSON.stringify({
@@ -7794,60 +7884,88 @@ function writeProcessInputStepReproCapture(params) {
7794
7884
  const addedMessageIds = contextMessages.map((message) => message.id).filter((id) => Boolean(id) && !preMessageIds.has(id));
7795
7885
  const idRemap = inferReproIdRemap(params.preMessages, contextMessages);
7796
7886
  const rawState = params.args.state ?? {};
7797
- const inputPayload = safeCaptureJson({
7798
- stepNumber: params.stepNumber,
7799
- threadId: params.threadId,
7800
- resourceId: params.resourceId,
7801
- readOnly: memoryContext?.memoryConfig?.readOnly,
7802
- messageCount: contextMessages.length,
7803
- messageIds: contextMessages.map((message) => message.id),
7804
- stateKeys: Object.keys(rawState),
7805
- state: rawState,
7806
- args: {
7807
- messages: params.args.messages,
7808
- steps: params.args.steps,
7809
- systemMessages: params.args.systemMessages,
7810
- retryCount: params.args.retryCount,
7811
- tools: params.args.tools,
7812
- toolChoice: params.args.toolChoice,
7813
- activeTools: params.args.activeTools,
7814
- providerOptions: params.args.providerOptions,
7815
- modelSettings: params.args.modelSettings,
7816
- structuredOutput: params.args.structuredOutput
7817
- }
7818
- });
7819
- const preStatePayload = safeCaptureJson({
7820
- record: params.preRecord,
7821
- bufferedChunks: params.preBufferedChunks,
7822
- contextTokenCount: params.preContextTokenCount,
7823
- messages: params.preMessages,
7824
- messageList: params.preSerializedMessageList
7825
- });
7826
- const outputPayload = safeCaptureJson({
7827
- details: params.details,
7828
- messageDiff: {
7829
- removedMessageIds,
7830
- addedMessageIds,
7831
- idRemap
7887
+ const sanitizedState = sanitizeCaptureState(rawState);
7888
+ const payloads = [
7889
+ {
7890
+ fileName: "input.json",
7891
+ data: {
7892
+ stepNumber: params.stepNumber,
7893
+ threadId: params.threadId,
7894
+ resourceId: params.resourceId,
7895
+ readOnly: memoryContext?.memoryConfig?.readOnly,
7896
+ messageCount: contextMessages.length,
7897
+ messageIds: contextMessages.map((message) => message.id),
7898
+ stateKeys: Object.keys(rawState),
7899
+ state: sanitizedState,
7900
+ args: {
7901
+ messages: params.args.messages,
7902
+ steps: params.args.steps,
7903
+ systemMessages: params.args.systemMessages,
7904
+ retryCount: params.args.retryCount,
7905
+ toolChoice: params.args.toolChoice,
7906
+ activeTools: params.args.activeTools,
7907
+ modelSettings: params.args.modelSettings,
7908
+ structuredOutput: params.args.structuredOutput
7909
+ }
7910
+ }
7911
+ },
7912
+ {
7913
+ fileName: "pre-state.json",
7914
+ data: {
7915
+ record: params.preRecord,
7916
+ bufferedChunks: params.preBufferedChunks,
7917
+ contextTokenCount: params.preContextTokenCount,
7918
+ messages: params.preMessages,
7919
+ messageList: params.preSerializedMessageList
7920
+ }
7921
+ },
7922
+ {
7923
+ fileName: "output.json",
7924
+ data: {
7925
+ details: params.details,
7926
+ messageDiff: {
7927
+ removedMessageIds,
7928
+ addedMessageIds,
7929
+ idRemap
7930
+ }
7931
+ }
7932
+ },
7933
+ {
7934
+ fileName: "post-state.json",
7935
+ data: {
7936
+ record: params.postRecord,
7937
+ bufferedChunks: params.postBufferedChunks,
7938
+ contextTokenCount: params.postContextTokenCount,
7939
+ messageCount: contextMessages.length,
7940
+ messageIds: contextMessages.map((message) => message.id),
7941
+ messages: contextMessages,
7942
+ messageList: params.messageList.serialize()
7943
+ }
7832
7944
  }
7833
- });
7834
- const postStatePayload = safeCaptureJson({
7835
- record: params.postRecord,
7836
- bufferedChunks: params.postBufferedChunks,
7837
- contextTokenCount: params.postContextTokenCount,
7838
- messageCount: contextMessages.length,
7839
- messageIds: contextMessages.map((message) => message.id),
7840
- messages: contextMessages,
7841
- messageList: params.messageList.serialize()
7842
- });
7843
- writeFileSync(join(captureDir, "input.json"), `${JSON.stringify(inputPayload, null, 2)}
7844
- `);
7845
- writeFileSync(join(captureDir, "pre-state.json"), `${JSON.stringify(preStatePayload, null, 2)}
7846
- `);
7847
- writeFileSync(join(captureDir, "output.json"), `${JSON.stringify(outputPayload, null, 2)}
7945
+ ];
7946
+ const captureErrors = [];
7947
+ for (const payload of payloads) {
7948
+ const serialized = safeCaptureJsonOrError(payload.data);
7949
+ if (serialized.ok) {
7950
+ writeFileSync(join(captureDir, payload.fileName), `${JSON.stringify(serialized.value, null, 2)}
7848
7951
  `);
7849
- writeFileSync(join(captureDir, "post-state.json"), `${JSON.stringify(postStatePayload, null, 2)}
7952
+ continue;
7953
+ }
7954
+ captureErrors.push({ fileName: payload.fileName, error: serialized.error });
7955
+ writeFileSync(
7956
+ join(captureDir, payload.fileName),
7957
+ `${JSON.stringify({ __captureError: serialized.error }, null, 2)}
7958
+ `
7959
+ );
7960
+ }
7961
+ if (captureErrors.length > 0) {
7962
+ writeFileSync(join(captureDir, "capture-error.json"), `${JSON.stringify(captureErrors, null, 2)}
7850
7963
  `);
7964
+ params.debug?.(
7965
+ `[OM:repro-capture] wrote processInputStep capture with ${captureErrors.length} serialization error(s) to ${captureDir}`
7966
+ );
7967
+ return;
7968
+ }
7851
7969
  params.debug?.(`[OM:repro-capture] wrote processInputStep capture to ${captureDir}`);
7852
7970
  } catch (error) {
7853
7971
  params.debug?.(`[OM:repro-capture] failed to write processInputStep capture: ${String(error)}`);
@@ -7870,7 +7988,17 @@ var ObservationalMemoryProcessor = class {
7870
7988
  }
7871
7989
  // ─── Processor lifecycle hooks ──────────────────────────────────────────
7872
7990
  async processInputStep(args) {
7873
- const { messageList, requestContext, stepNumber, state: _state, writer, model, abortSignal, abort } = args;
7991
+ const {
7992
+ messageList,
7993
+ requestContext,
7994
+ stepNumber,
7995
+ state: _state,
7996
+ writer,
7997
+ model,
7998
+ abortSignal,
7999
+ abort,
8000
+ rotateResponseMessageId
8001
+ } = args;
7874
8002
  const state = _state ?? {};
7875
8003
  omDebug(
7876
8004
  `[OM:processInputStep:ENTER] step=${stepNumber}, hasMastraMemory=${!!requestContext?.get("MastraMemory")}, hasMemoryInfo=${!!messageList?.serialize()?.memoryInfo?.threadId}`
@@ -7898,7 +8026,14 @@ var ObservationalMemoryProcessor = class {
7898
8026
  await this.turn.end().catch(() => {
7899
8027
  });
7900
8028
  }
7901
- this.turn = this.engine.beginTurn({ threadId, resourceId, messageList });
8029
+ this.turn = this.engine.beginTurn({
8030
+ threadId,
8031
+ resourceId,
8032
+ messageList,
8033
+ hooks: {
8034
+ onBufferChunkSealed: rotateResponseMessageId
8035
+ }
8036
+ });
7902
8037
  this.turn.writer = writer;
7903
8038
  this.turn.requestContext = requestContext;
7904
8039
  await this.turn.start(this.memory);
@@ -8033,5 +8168,5 @@ function getObservationsAsOf(activeObservations, asOf) {
8033
8168
  }
8034
8169
 
8035
8170
  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 };
8036
- //# sourceMappingURL=chunk-2QSOQQPM.js.map
8037
- //# sourceMappingURL=chunk-2QSOQQPM.js.map
8171
+ //# sourceMappingURL=chunk-SKRONGCV.js.map
8172
+ //# sourceMappingURL=chunk-SKRONGCV.js.map