@mastra/memory 1.39.0-alpha.2 → 1.39.0-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.
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/processors/index.cjs +1 -1
- package/dist/processors/index.js +1 -1
- package/dist/processors/observational-memory/observation-turn/step.d.ts +2 -0
- package/dist/processors/observational-memory/observation-turn/step.d.ts.map +1 -1
- package/dist/processors/observational-memory/observation-turn/turn.d.ts +13 -0
- package/dist/processors/observational-memory/observation-turn/turn.d.ts.map +1 -1
- package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
- package/dist/processors/observational-memory/processor.d.ts.map +1 -1
- package/dist/processors/observational-memory/reflector-runner.d.ts +3 -0
- package/dist/processors/observational-memory/reflector-runner.d.ts.map +1 -1
- package/dist/{src-BDhP0_OK.js → src-Dg8w4Ud-.js} +93 -9
- package/dist/{src-BDhP0_OK.js.map → src-Dg8w4Ud-.js.map} +1 -1
- package/dist/{src-CJiR-m2F.cjs → src-GHUZVCL8.cjs} +93 -9
- package/dist/{src-CJiR-m2F.cjs.map → src-GHUZVCL8.cjs.map} +1 -1
- package/package.json +5 -4
|
@@ -28598,6 +28598,7 @@ var ObservationStep = class {
|
|
|
28598
28598
|
let observerExchange;
|
|
28599
28599
|
const step0Messages = this.stepNumber === 0 ? getObservableMessages(messageList) : [];
|
|
28600
28600
|
if (this.stepNumber === 0) {
|
|
28601
|
+
this.turn.inputMessageIds = messageList.get.input.db().map((msg) => msg.id);
|
|
28601
28602
|
const activation = await om.activate({
|
|
28602
28603
|
threadId,
|
|
28603
28604
|
resourceId,
|
|
@@ -28705,13 +28706,27 @@ var ObservationStep = class {
|
|
|
28705
28706
|
}
|
|
28706
28707
|
const bandDefersObservation = statusSnapshot.inAsyncObservationBand && !statusSnapshot.canActivate;
|
|
28707
28708
|
const willObserveNow = statusSnapshot.shouldObserve && !hasIncompleteToolCalls && !bandDefersObservation;
|
|
28708
|
-
/**
|
|
28709
|
-
|
|
28709
|
+
/**
|
|
28710
|
+
* In-flight message ids cleanup must never remove from live context: the turn's own
|
|
28711
|
+
* request, plus whatever the model has not read yet (the pending messages at step 0, the
|
|
28712
|
+
* previous step's output — e.g. a tool result — at step > 0).
|
|
28713
|
+
*/
|
|
28714
|
+
let inFlightIds;
|
|
28710
28715
|
if (this.stepNumber > 0 || willObserveNow) {
|
|
28711
28716
|
if (this.stepNumber > 0) {
|
|
28712
28717
|
const newInput = messageList.clear.input.db();
|
|
28713
28718
|
const newOutput = messageList.clear.response.db();
|
|
28714
28719
|
const messagesToSave = [...newInput, ...newOutput];
|
|
28720
|
+
const drainedIds = new Set(messagesToSave.map((msg) => msg.id));
|
|
28721
|
+
const updatedEarlier = messageList.get.all.db().filter((msg) => !drainedIds.has(msg.id) && this.turn.drainedPartKeys.has(msg.id));
|
|
28722
|
+
const drainedKeys = /* @__PURE__ */ new Map();
|
|
28723
|
+
const unreadIds = [...messagesToSave, ...updatedEarlier].filter((msg) => {
|
|
28724
|
+
const keys = getPartKeys(msg);
|
|
28725
|
+
const seen = this.turn.drainedPartKeys.get(msg.id);
|
|
28726
|
+
drainedKeys.set(msg.id, /* @__PURE__ */ new Set([...seen ?? [], ...keys]));
|
|
28727
|
+
return !seen || keys.some((key) => !seen.has(key));
|
|
28728
|
+
}).map((msg) => msg.id);
|
|
28729
|
+
inFlightIds = [.../* @__PURE__ */ new Set([...this.turn.inputMessageIds, ...unreadIds])];
|
|
28715
28730
|
if (messagesToSave.length > 0) {
|
|
28716
28731
|
for (const msg of messagesToSave) messageList.add(msg, "memory");
|
|
28717
28732
|
try {
|
|
@@ -28722,10 +28737,11 @@ var ObservationStep = class {
|
|
|
28722
28737
|
throw error;
|
|
28723
28738
|
}
|
|
28724
28739
|
}
|
|
28740
|
+
for (const [id, keys] of drainedKeys) this.turn.drainedPartKeys.set(id, keys);
|
|
28725
28741
|
} else {
|
|
28726
28742
|
const pending = [...messageList.get.input.db(), ...messageList.get.response.db()];
|
|
28727
28743
|
if (pending.length > 0) await om.persistMessages(pending, threadId, resourceId);
|
|
28728
|
-
|
|
28744
|
+
inFlightIds = pending.map((msg) => msg.id);
|
|
28729
28745
|
}
|
|
28730
28746
|
if (this.stepNumber === 0 && willObserveNow && this.turn.responseMessageId) {
|
|
28731
28747
|
const seed = {
|
|
@@ -28759,7 +28775,7 @@ var ObservationStep = class {
|
|
|
28759
28775
|
messages: messageList,
|
|
28760
28776
|
observedMessageIds: observedIds,
|
|
28761
28777
|
retentionFloor: minRemaining,
|
|
28762
|
-
preserveMessageIds:
|
|
28778
|
+
preserveMessageIds: [...inFlightIds ?? [], ...this.changedSinceDrain(messageList)]
|
|
28763
28779
|
});
|
|
28764
28780
|
if (statusSnapshot.asyncObservationEnabled) await om.resetBufferingState({
|
|
28765
28781
|
threadId,
|
|
@@ -28787,7 +28803,7 @@ var ObservationStep = class {
|
|
|
28787
28803
|
});
|
|
28788
28804
|
if (!didThresholdCleanup) {
|
|
28789
28805
|
const fallbackCursor = this.turn.record.threadId ? (0, _mastra_core_memory.getThreadOMMetadata)((await om.getStorage().getThreadById({ threadId: this.turn.record.threadId }))?.metadata)?.lastObservedMessageCursor : void 0;
|
|
28790
|
-
const pendingMessageIds = new Set([...messageList.get.input.db(), ...messageList.get.response.db()].map((msg) => msg.id).filter(Boolean));
|
|
28806
|
+
const pendingMessageIds = new Set([...messageList.get.input.db(), ...messageList.get.response.db()].map((msg) => msg.id).concat(inFlightIds ?? [], this.turn.inputMessageIds, this.changedSinceDrain(messageList)).filter(Boolean));
|
|
28791
28807
|
filterObservedMessages({
|
|
28792
28808
|
messageList,
|
|
28793
28809
|
record: this.turn.record,
|
|
@@ -28816,6 +28832,13 @@ var ObservationStep = class {
|
|
|
28816
28832
|
this._prepared = true;
|
|
28817
28833
|
return this._context;
|
|
28818
28834
|
}
|
|
28835
|
+
/** Ids of already-drained messages that now hold parts the model has not been sent. */
|
|
28836
|
+
changedSinceDrain(messageList) {
|
|
28837
|
+
return messageList.get.all.db().filter((msg) => {
|
|
28838
|
+
const seen = this.turn.drainedPartKeys.get(msg.id);
|
|
28839
|
+
return seen !== void 0 && getPartKeys(msg).some((key) => !seen.has(key));
|
|
28840
|
+
}).map((msg) => msg.id);
|
|
28841
|
+
}
|
|
28819
28842
|
/**
|
|
28820
28843
|
* Run the full threshold observation pipeline:
|
|
28821
28844
|
* waitForBuffering → re-check → activate buffered chunks → reflect → observe
|
|
@@ -28988,6 +29011,49 @@ function restoreDrainedMessages(messageList, drained, source) {
|
|
|
28988
29011
|
const ids = drained.map((msg) => msg.id).filter((id) => !stillQueued.has(id));
|
|
28989
29012
|
for (const msg of messageList.removeByIds(ids)) messageList.add(msg, source, { merge: false });
|
|
28990
29013
|
}
|
|
29014
|
+
/**
|
|
29015
|
+
* Identity keys of a message's non-marker parts. Tool parts are keyed by call id, state and result,
|
|
29016
|
+
* so a result merged in place into an existing tool-invocation part yields a new key. Bookkeeping
|
|
29017
|
+
* fields that change when a part is re-stamped are not part of the identity.
|
|
29018
|
+
*/
|
|
29019
|
+
function getPartKeys(msg) {
|
|
29020
|
+
const seen = /* @__PURE__ */ new Map();
|
|
29021
|
+
return (msg.content.parts ?? []).flatMap((part) => {
|
|
29022
|
+
if (part.type.startsWith("data-om-")) return [];
|
|
29023
|
+
let identity;
|
|
29024
|
+
if (part.type === "tool-invocation") identity = toolPartIdentity(part.toolInvocation);
|
|
29025
|
+
else {
|
|
29026
|
+
const { providerMetadata: _providerMetadata, createdAt: _createdAt, updatedAt: _updatedAt, ...rest } = part;
|
|
29027
|
+
identity = JSON.stringify(rest);
|
|
29028
|
+
}
|
|
29029
|
+
const ordinal = seen.get(identity) ?? 0;
|
|
29030
|
+
seen.set(identity, ordinal + 1);
|
|
29031
|
+
return [`${identity}#${ordinal}`];
|
|
29032
|
+
});
|
|
29033
|
+
}
|
|
29034
|
+
/**
|
|
29035
|
+
* Serializing a tool result on every step is quadratic in turn length (each step rescans every drained
|
|
29036
|
+
* message), so the identity is cached per invocation object and reused while its state and result
|
|
29037
|
+
* reference are unchanged. A result merged in place replaces that reference and is re-serialized.
|
|
29038
|
+
*/
|
|
29039
|
+
const toolPartIdentityCache = /* @__PURE__ */ new WeakMap();
|
|
29040
|
+
function toolPartIdentity(invocation) {
|
|
29041
|
+
const result = invocation.state === "result" ? invocation.result : null;
|
|
29042
|
+
const cached = toolPartIdentityCache.get(invocation);
|
|
29043
|
+
if (cached && cached.state === invocation.state && cached.result === result) return cached.identity;
|
|
29044
|
+
const identity = JSON.stringify([
|
|
29045
|
+
"tool-invocation",
|
|
29046
|
+
invocation.toolCallId,
|
|
29047
|
+
invocation.state,
|
|
29048
|
+
result
|
|
29049
|
+
]);
|
|
29050
|
+
toolPartIdentityCache.set(invocation, {
|
|
29051
|
+
state: invocation.state,
|
|
29052
|
+
result,
|
|
29053
|
+
identity
|
|
29054
|
+
});
|
|
29055
|
+
return identity;
|
|
29056
|
+
}
|
|
28991
29057
|
//#endregion
|
|
28992
29058
|
//#region src/processors/observational-memory/observation-turn/turn.ts
|
|
28993
29059
|
/**
|
|
@@ -29021,6 +29087,19 @@ var ObservationTurn = class {
|
|
|
29021
29087
|
_ended = false;
|
|
29022
29088
|
/** Generation count at turn start — used to detect if reflection happened during the turn. */
|
|
29023
29089
|
_generationCountAtStart = -1;
|
|
29090
|
+
/**
|
|
29091
|
+
* Ids of the messages this turn was started with (the user's request). Mid-turn
|
|
29092
|
+
* observation may record them, but they stay in the live prompt until the turn ends.
|
|
29093
|
+
* @internal Set by step 0.
|
|
29094
|
+
*/
|
|
29095
|
+
inputMessageIds = [];
|
|
29096
|
+
/**
|
|
29097
|
+
* Fingerprints of the non-marker parts each message had when a step last drained it. A message
|
|
29098
|
+
* is unread step output only if it gained a part the model has not seen — including a tool result
|
|
29099
|
+
* merged in place into an existing tool-invocation part — not when it only gained OM markers.
|
|
29100
|
+
* @internal
|
|
29101
|
+
*/
|
|
29102
|
+
drainedPartKeys = /* @__PURE__ */ new Map();
|
|
29024
29103
|
/** Memory context provider — set via start(). Used by steps for beforeBuffer persistence. */
|
|
29025
29104
|
memory;
|
|
29026
29105
|
/** Optional stream writer for emitting markers. */
|
|
@@ -29618,6 +29697,7 @@ var ReflectorRunner = class {
|
|
|
29618
29697
|
* number per active thread/resource key and live for the runner's lifetime.
|
|
29619
29698
|
*/
|
|
29620
29699
|
syncReflectionSuppression = /* @__PURE__ */ new Map();
|
|
29700
|
+
trackBackgroundWork;
|
|
29621
29701
|
constructor(opts) {
|
|
29622
29702
|
this.reflectionConfig = opts.reflectionConfig;
|
|
29623
29703
|
this.observationConfig = opts.observationConfig;
|
|
@@ -29634,6 +29714,7 @@ var ReflectorRunner = class {
|
|
|
29634
29714
|
this.memory = opts.memory;
|
|
29635
29715
|
this.onReflectionCommitted = opts.onReflectionCommitted;
|
|
29636
29716
|
this.hooks = opts.hooks;
|
|
29717
|
+
this.trackBackgroundWork = opts.trackBackgroundWork;
|
|
29637
29718
|
}
|
|
29638
29719
|
__registerMastra(mastra) {
|
|
29639
29720
|
this.mastra = mastra;
|
|
@@ -29891,10 +29972,11 @@ var ReflectorRunner = class {
|
|
|
29891
29972
|
if (this.buffering.isAsyncBufferingInProgress(bufferKey)) return;
|
|
29892
29973
|
BufferingCoordinator.lastBufferedBoundary.set(bufferKey, observationTokens);
|
|
29893
29974
|
registerOp(record.id, "bufferingReflection");
|
|
29894
|
-
this.storage.setBufferingReflectionFlag(record.id, true).catch((err) => {
|
|
29975
|
+
const flagSet = this.storage.setBufferingReflectionFlag(record.id, true).catch((err) => {
|
|
29895
29976
|
omError("[OM] Failed to set buffering reflection flag", err);
|
|
29896
29977
|
});
|
|
29897
29978
|
const asyncOp = (async () => {
|
|
29979
|
+
await flagSet;
|
|
29898
29980
|
let outcome;
|
|
29899
29981
|
let reflectionError;
|
|
29900
29982
|
try {
|
|
@@ -29935,12 +30017,13 @@ var ReflectorRunner = class {
|
|
|
29935
30017
|
}
|
|
29936
30018
|
BufferingCoordinator.asyncBufferingOps.delete(bufferKey);
|
|
29937
30019
|
unregisterOp(record.id, "bufferingReflection");
|
|
29938
|
-
this.storage.setBufferingReflectionFlag(record.id, false).catch((err) => {
|
|
30020
|
+
await this.storage.setBufferingReflectionFlag(record.id, false).catch((err) => {
|
|
29939
30021
|
omError("[OM] Failed to clear buffering reflection flag", err);
|
|
29940
30022
|
});
|
|
29941
30023
|
}
|
|
29942
30024
|
})();
|
|
29943
30025
|
BufferingCoordinator.asyncBufferingOps.set(bufferKey, asyncOp);
|
|
30026
|
+
this.trackBackgroundWork?.(asyncOp);
|
|
29944
30027
|
}
|
|
29945
30028
|
/**
|
|
29946
30029
|
* Perform async buffered reflection — reflects observations and stores to bufferedReflection.
|
|
@@ -31149,7 +31232,8 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
31149
31232
|
mastra: config.mastra,
|
|
31150
31233
|
memory: this.memory,
|
|
31151
31234
|
onReflectionCommitted: config.onReflectionCommitted,
|
|
31152
|
-
hooks: this.hooks
|
|
31235
|
+
hooks: this.hooks,
|
|
31236
|
+
trackBackgroundWork: (work) => this.trackBackgroundWork(work)
|
|
31153
31237
|
});
|
|
31154
31238
|
this.validateBufferConfig();
|
|
31155
31239
|
if (this.scope === "resource" && !hasWarnedResourceScopeDeprecation) {
|
|
@@ -36757,4 +36841,4 @@ Object.defineProperty(exports, "wrapInObservationGroup", {
|
|
|
36757
36841
|
}
|
|
36758
36842
|
});
|
|
36759
36843
|
|
|
36760
|
-
//# sourceMappingURL=src-
|
|
36844
|
+
//# sourceMappingURL=src-GHUZVCL8.cjs.map
|