@mastra/memory 1.27.0-alpha.0 → 1.27.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.
- package/CHANGELOG.md +28 -0
- package/dist/docs/SKILL.md +7 -6
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/{docs-agents-agent-approval.md → docs-agents-human-in-the-loop.md} +5 -5
- package/dist/docs/references/docs-agents-networks.md +3 -3
- package/dist/docs/references/{docs-long-running-agents-background-tasks.md → docs-harness-background-tasks.md} +5 -5
- package/dist/docs/references/{docs-long-running-agents-goals.md → docs-harness-goals.md} +6 -6
- package/dist/docs/references/docs-memory-message-history.md +1 -1
- package/dist/docs/references/docs-memory-overview.md +4 -4
- package/dist/docs/references/docs-memory-working-memory.md +1 -1
- package/dist/docs/references/{docs-storage-overview.md → docs-storage.md} +1 -1
- package/dist/docs/references/{docs-capabilities-subagents.md → docs-subagents.md} +35 -5
- package/dist/docs/references/integrations-channels-github.md +1 -1
- package/dist/docs/references/integrations-databases-postgresql.md +1 -0
- package/dist/docs/references/reference-file-based-agents-memory.md +2 -2
- package/dist/docs/references/reference-memory-memory-class.md +1 -0
- package/dist/docs/references/reference-memory-settled.md +57 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +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.map +1 -1
- package/dist/processors/observational-memory/observation-turn/turn.d.ts.map +1 -1
- package/dist/processors/observational-memory/observational-memory.d.ts +19 -0
- 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.map +1 -1
- package/dist/processors/observational-memory/types.d.ts +2 -0
- package/dist/processors/observational-memory/types.d.ts.map +1 -1
- package/dist/{src-BUlG9vaB.js → src-C-nmWgoF.js} +74 -11
- package/dist/{src-BUlG9vaB.js.map → src-C-nmWgoF.js.map} +1 -1
- package/dist/{src-MvtBOFYO.cjs → src-Drm6l_ZN.cjs} +74 -11
- package/dist/{src-MvtBOFYO.cjs.map → src-Drm6l_ZN.cjs.map} +1 -1
- package/dist/tools/working-memory.d.ts +3 -1
- package/dist/tools/working-memory.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -19903,21 +19903,22 @@ const SET_WORKING_MEMORY_TOOL_NAME = "setWorkingMemory";
|
|
|
19903
19903
|
/**
|
|
19904
19904
|
* Deep merges two objects, with special handling for null values (delete) and arrays (replace).
|
|
19905
19905
|
* - Object properties are recursively merged
|
|
19906
|
-
* - null values in the update will delete the corresponding property
|
|
19906
|
+
* - null values in the update will delete the corresponding property, even when the property
|
|
19907
|
+
* or its parent object does not exist yet (so padded nulls never get stored literally)
|
|
19907
19908
|
* - Arrays are replaced entirely (not merged element-by-element)
|
|
19908
19909
|
* - Primitive values are overwritten
|
|
19910
|
+
* - The returned object is always newly constructed and never aliases `update`
|
|
19909
19911
|
*/
|
|
19910
19912
|
function deepMergeWorkingMemory(existing, update) {
|
|
19911
19913
|
if (!update || typeof update !== "object" || Object.keys(update).length === 0) return existing && typeof existing === "object" ? { ...existing } : {};
|
|
19912
|
-
|
|
19913
|
-
const result = { ...existing };
|
|
19914
|
+
const result = { ...existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {} };
|
|
19914
19915
|
for (const key of Object.keys(update)) {
|
|
19915
19916
|
const updateValue = update[key];
|
|
19916
19917
|
const existingValue = result[key];
|
|
19917
19918
|
if (updateValue === void 0) continue;
|
|
19918
19919
|
if (updateValue === null) delete result[key];
|
|
19919
19920
|
else if (Array.isArray(updateValue)) result[key] = updateValue;
|
|
19920
|
-
else if (typeof updateValue === "object"
|
|
19921
|
+
else if (typeof updateValue === "object") result[key] = deepMergeWorkingMemory(existingValue && typeof existingValue === "object" && !Array.isArray(existingValue) ? existingValue : void 0, updateValue);
|
|
19921
19922
|
else result[key] = updateValue;
|
|
19922
19923
|
}
|
|
19923
19924
|
return result;
|
|
@@ -22294,7 +22295,7 @@ var ObservationStep = class {
|
|
|
22294
22295
|
messageList.removeByIds(candidates.map((msg) => msg.id));
|
|
22295
22296
|
for (const msg of candidates) messageList.add(msg, "memory");
|
|
22296
22297
|
}
|
|
22297
|
-
om.buffer({
|
|
22298
|
+
om.trackBackgroundWork(om.buffer({
|
|
22298
22299
|
threadId,
|
|
22299
22300
|
resourceId,
|
|
22300
22301
|
messages: unobservedMessages,
|
|
@@ -22305,7 +22306,7 @@ var ObservationStep = class {
|
|
|
22305
22306
|
observabilityContext: this.turn.observabilityContext
|
|
22306
22307
|
}).catch((err) => {
|
|
22307
22308
|
omDebug(`[OM:buffer] fire-and-forget buffer failed: ${err?.message}`);
|
|
22308
|
-
});
|
|
22309
|
+
}));
|
|
22309
22310
|
buffered = true;
|
|
22310
22311
|
}
|
|
22311
22312
|
const willObserveNow = statusSnapshot.shouldObserve && !hasIncompleteToolCalls;
|
|
@@ -22673,7 +22674,7 @@ var ObservationTurn = class {
|
|
|
22673
22674
|
const allMessages = getObservableMessages(this.messageList);
|
|
22674
22675
|
const record = this._record;
|
|
22675
22676
|
const unobservedMessages = this.om.getUnobservedMessages(allMessages, record);
|
|
22676
|
-
if (unobservedMessages.length > 0) this.om.buffer({
|
|
22677
|
+
if (unobservedMessages.length > 0) this.om.trackBackgroundWork(this.om.buffer({
|
|
22677
22678
|
threadId: this.threadId,
|
|
22678
22679
|
resourceId: this.resourceId,
|
|
22679
22680
|
messages: unobservedMessages,
|
|
@@ -22687,7 +22688,7 @@ var ObservationTurn = class {
|
|
|
22687
22688
|
skipMinimumTokenCheck: true
|
|
22688
22689
|
}).catch((err) => {
|
|
22689
22690
|
omDebug(`[OM:turn.end] idle buffer failed: ${err?.message}`);
|
|
22690
|
-
});
|
|
22691
|
+
}));
|
|
22691
22692
|
}
|
|
22692
22693
|
return { record: this._record };
|
|
22693
22694
|
}
|
|
@@ -23171,6 +23172,8 @@ var ReflectorRunner = class {
|
|
|
23171
23172
|
};
|
|
23172
23173
|
let reflectedTokens = 0;
|
|
23173
23174
|
let attemptNumber = 0;
|
|
23175
|
+
/** Observations from the previous attempt, used to detect a no-progress ladder. */
|
|
23176
|
+
let previousObservations;
|
|
23174
23177
|
while (currentLevel <= maxLevel) {
|
|
23175
23178
|
attemptNumber++;
|
|
23176
23179
|
const isRetry = attemptNumber > 1;
|
|
@@ -23244,6 +23247,11 @@ var ReflectorRunner = class {
|
|
|
23244
23247
|
omDebug(`[OM:callReflector] degenerate output persists at maxLevel=${maxLevel}, breaking`);
|
|
23245
23248
|
break;
|
|
23246
23249
|
}
|
|
23250
|
+
if (!parsed.degenerate && previousObservations !== void 0 && parsed.observations === previousObservations) {
|
|
23251
|
+
omDebug(`[OM:callReflector] attempt #${attemptNumber} returned output identical to the previous attempt; escalating cannot help, stopping the ladder`);
|
|
23252
|
+
break;
|
|
23253
|
+
}
|
|
23254
|
+
previousObservations = parsed.observations;
|
|
23247
23255
|
if (streamContext?.writer) {
|
|
23248
23256
|
const failedMarker = createObservationFailedMarker({
|
|
23249
23257
|
cycleId: streamContext.cycleId,
|
|
@@ -24222,6 +24230,39 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
24222
24230
|
*/
|
|
24223
24231
|
recordInitializations = /* @__PURE__ */ new Map();
|
|
24224
24232
|
/**
|
|
24233
|
+
* In-flight fire-and-forget background cycles (buffered observation, reflection).
|
|
24234
|
+
* Tracked so callers can join them via `settled()` before closing a storage
|
|
24235
|
+
* connection they own — otherwise a background cycle's tail statements race the close.
|
|
24236
|
+
*/
|
|
24237
|
+
pendingBackgroundWork = /* @__PURE__ */ new Set();
|
|
24238
|
+
/**
|
|
24239
|
+
* Register fire-and-forget background work so `settled()` can join it.
|
|
24240
|
+
* Returns the original promise so callers keep their own rejection handling.
|
|
24241
|
+
*/
|
|
24242
|
+
trackBackgroundWork(work) {
|
|
24243
|
+
const tracked = work.catch(() => {}).finally(() => {
|
|
24244
|
+
this.pendingBackgroundWork.delete(tracked);
|
|
24245
|
+
});
|
|
24246
|
+
this.pendingBackgroundWork.add(tracked);
|
|
24247
|
+
return work;
|
|
24248
|
+
}
|
|
24249
|
+
/**
|
|
24250
|
+
* Resolve once all background observational-memory work started so far has finished.
|
|
24251
|
+
*
|
|
24252
|
+
* Background cycles enqueue further background work (a buffered observation can
|
|
24253
|
+
* trigger a reflection, which runs nested agent streams), so this drains repeatedly
|
|
24254
|
+
* until nothing is left rather than joining a single snapshot.
|
|
24255
|
+
*/
|
|
24256
|
+
async settled() {
|
|
24257
|
+
const maxDrainRounds = 100;
|
|
24258
|
+
for (let round = 0; round < maxDrainRounds; round++) {
|
|
24259
|
+
if (this.pendingBackgroundWork.size === 0) return;
|
|
24260
|
+
await Promise.allSettled([...this.pendingBackgroundWork]);
|
|
24261
|
+
}
|
|
24262
|
+
if (this.pendingBackgroundWork.size === 0) return;
|
|
24263
|
+
omError(`[OM:settled] background work still pending after ${maxDrainRounds} drain rounds; giving up waiting`);
|
|
24264
|
+
}
|
|
24265
|
+
/**
|
|
24225
24266
|
* Acquire a lock for the given key, execute the callback, then release.
|
|
24226
24267
|
* If a lock is already held, waits for it to be released before acquiring.
|
|
24227
24268
|
*/
|
|
@@ -25222,7 +25263,7 @@ ${formattedMessages}
|
|
|
25222
25263
|
if (!this.buffering.isAsyncObservationEnabled()) return false;
|
|
25223
25264
|
const lockKey = this.buffering.getLockKey(opts.threadId, opts.resourceId);
|
|
25224
25265
|
const shouldTrigger = this.buffering.shouldTriggerAsyncObservation(opts.pendingTokens, lockKey, opts.record, this.storage, opts.threshold);
|
|
25225
|
-
if (shouldTrigger) this.startAsyncBufferedObservation(opts.record, opts.threadId, opts.unobservedMessages, lockKey, opts.writer, opts.unbufferedPendingTokens, opts.requestContext);
|
|
25266
|
+
if (shouldTrigger) this.trackBackgroundWork(this.startAsyncBufferedObservation(opts.record, opts.threadId, opts.unobservedMessages, lockKey, opts.writer, opts.unbufferedPendingTokens, opts.requestContext));
|
|
25226
25267
|
return shouldTrigger;
|
|
25227
25268
|
}
|
|
25228
25269
|
isMessageList(value) {
|
|
@@ -25535,7 +25576,10 @@ ${formattedMessages}
|
|
|
25535
25576
|
}
|
|
25536
25577
|
};
|
|
25537
25578
|
omDebug(`[OM:status] step=${stepNumber} msgs=${pendingTokens}/${threshold} obs=${currentObservationTokens}/${effectiveObservationTokensThreshold} gen=${record.generationCount}`);
|
|
25538
|
-
await writer.custom(
|
|
25579
|
+
await writer.custom({
|
|
25580
|
+
...statusPart,
|
|
25581
|
+
transient: true
|
|
25582
|
+
}).catch(() => {});
|
|
25539
25583
|
}
|
|
25540
25584
|
}
|
|
25541
25585
|
/**
|
|
@@ -27049,6 +27093,25 @@ var Memory = class extends _mastra_core_memory.MastraMemory {
|
|
|
27049
27093
|
trackVectorCleanup(cleanup) {
|
|
27050
27094
|
this.pendingVectorCleanup = Promise.allSettled([this.pendingVectorCleanup, cleanup]).then(() => void 0);
|
|
27051
27095
|
}
|
|
27096
|
+
/**
|
|
27097
|
+
* Resolve once all background work this Memory started has finished: observational-memory
|
|
27098
|
+
* cycles (buffered observation and reflection, including the nested agent runs they spawn)
|
|
27099
|
+
* and vector cleanup from `deleteThread` / `deleteMessages`.
|
|
27100
|
+
*
|
|
27101
|
+
* Callers that own the storage connection should await this before closing it, otherwise
|
|
27102
|
+
* background statements can race the close.
|
|
27103
|
+
*
|
|
27104
|
+
* ```ts
|
|
27105
|
+
* await agent.generate('hello', { memory: { thread, resource } });
|
|
27106
|
+
* await memory.settled();
|
|
27107
|
+
* await store.close();
|
|
27108
|
+
* ```
|
|
27109
|
+
*/
|
|
27110
|
+
async settled() {
|
|
27111
|
+
await this.pendingVectorCleanup;
|
|
27112
|
+
await (this._omEngine ? await this._omEngine : this._omEngineInstance)?.settled();
|
|
27113
|
+
await this.pendingVectorCleanup;
|
|
27114
|
+
}
|
|
27052
27115
|
/** The shared ObservationalMemory engine. Lazily created on first access. */
|
|
27053
27116
|
get omEngine() {
|
|
27054
27117
|
if (!this._omEngine) this._omEngine = this._initOMEngine().then((engine) => {
|
|
@@ -29046,4 +29109,4 @@ Object.defineProperty(exports, "wrapInObservationGroup", {
|
|
|
29046
29109
|
}
|
|
29047
29110
|
});
|
|
29048
29111
|
|
|
29049
|
-
//# sourceMappingURL=src-
|
|
29112
|
+
//# sourceMappingURL=src-Drm6l_ZN.cjs.map
|