@mastra/memory 1.27.0-alpha.3 → 1.27.1-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.
- package/CHANGELOG.md +74 -0
- package/dist/docs/SKILL.md +2 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-guides-context-engineering.md +297 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +6 -3
- 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-strategies/async-buffer.d.ts.map +1 -1
- package/dist/processors/observational-memory/observation-strategies/sync.d.ts.map +1 -1
- package/dist/processors/observational-memory/observation-turn/load-memory-context.d.ts +3 -1
- package/dist/processors/observational-memory/observation-turn/load-memory-context.d.ts.map +1 -1
- package/dist/processors/observational-memory/observation-turn/turn.d.ts +2 -1
- package/dist/processors/observational-memory/observation-turn/turn.d.ts.map +1 -1
- package/dist/processors/observational-memory/observer-agent.d.ts +13 -0
- package/dist/processors/observational-memory/observer-agent.d.ts.map +1 -1
- package/dist/processors/observational-memory/observer-runner.d.ts.map +1 -1
- package/dist/processors/observational-memory/processor.d.ts +2 -0
- 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/tracing.d.ts.map +1 -1
- package/dist/{src-t_4yoTX9.js → src-BlQjkJzk.js} +129 -44
- package/dist/{src-t_4yoTX9.js.map → src-BlQjkJzk.js.map} +1 -1
- package/dist/{src-Ik0ksTOt.cjs → src-bE5dqCVp.cjs} +129 -44
- package/dist/{src-Ik0ksTOt.cjs.map → src-bE5dqCVp.cjs.map} +1 -1
- package/package.json +7 -7
|
@@ -18966,6 +18966,52 @@ function detectDegenerateRepetition(text) {
|
|
|
18966
18966
|
return false;
|
|
18967
18967
|
}
|
|
18968
18968
|
/**
|
|
18969
|
+
* Build a single-line diagnostic description of output flagged by
|
|
18970
|
+
* {@link detectDegenerateRepetition}. Used when logging or surfacing a
|
|
18971
|
+
* degenerate-output failure so the discarded model output can be inspected —
|
|
18972
|
+
* without it there is no way to tell a real repetition loop apart from a
|
|
18973
|
+
* detector false-positive on legitimately repetitive content.
|
|
18974
|
+
*
|
|
18975
|
+
* Reuses the detector's sampling parameters (200-char windows, ~50 samples)
|
|
18976
|
+
* so the reported duplicate ratio and most-repeated window match what
|
|
18977
|
+
* triggered the detection. Snippets are JSON-escaped so the result stays on
|
|
18978
|
+
* one line.
|
|
18979
|
+
*/
|
|
18980
|
+
function describeDegenerateOutput(text, snippetChars = 400) {
|
|
18981
|
+
const windowSize = 200;
|
|
18982
|
+
const step = Math.max(1, Math.floor(text.length / 50));
|
|
18983
|
+
const seen = /* @__PURE__ */ new Map();
|
|
18984
|
+
let duplicateWindows = 0;
|
|
18985
|
+
let totalWindows = 0;
|
|
18986
|
+
for (let i = 0; i + windowSize <= text.length; i += step) {
|
|
18987
|
+
const window = text.slice(i, i + windowSize);
|
|
18988
|
+
totalWindows++;
|
|
18989
|
+
const count = (seen.get(window) ?? 0) + 1;
|
|
18990
|
+
seen.set(window, count);
|
|
18991
|
+
if (count > 1) duplicateWindows++;
|
|
18992
|
+
}
|
|
18993
|
+
let topWindow = "";
|
|
18994
|
+
let topCount = 0;
|
|
18995
|
+
for (const [window, count] of seen) if (count > topCount) {
|
|
18996
|
+
topCount = count;
|
|
18997
|
+
topWindow = window;
|
|
18998
|
+
}
|
|
18999
|
+
let longestLine = 0;
|
|
19000
|
+
for (const line of text.split("\n")) if (line.length > longestLine) longestLine = line.length;
|
|
19001
|
+
const duplicateRatio = totalWindows > 0 ? (duplicateWindows / totalWindows).toFixed(2) : "n/a";
|
|
19002
|
+
const parts = [
|
|
19003
|
+
`length=${text.length}`,
|
|
19004
|
+
`sampledWindows=${totalWindows}`,
|
|
19005
|
+
`duplicateRatio=${duplicateRatio}`,
|
|
19006
|
+
`longestLine=${longestLine}`,
|
|
19007
|
+
`topWindowCount=${topCount}`
|
|
19008
|
+
];
|
|
19009
|
+
if (topCount > 1) parts.push(`topWindow=${JSON.stringify(topWindow)}`);
|
|
19010
|
+
parts.push(`head=${JSON.stringify(text.slice(0, snippetChars))}`);
|
|
19011
|
+
if (text.length > snippetChars * 2) parts.push(`tail=${JSON.stringify(text.slice(-snippetChars))}`);
|
|
19012
|
+
return parts.join(" ");
|
|
19013
|
+
}
|
|
19014
|
+
/**
|
|
18969
19015
|
* Check if observations contain a Current Task section.
|
|
18970
19016
|
* Supports both XML format and legacy markdown format.
|
|
18971
19017
|
*/
|
|
@@ -19230,7 +19276,19 @@ async function withOmTracingSpan({ phase, model, inputTokens, requestContext, ob
|
|
|
19230
19276
|
});
|
|
19231
19277
|
const childObservabilityContext = (0, _mastra_core_observability.createObservabilityContext)({ currentSpan: span });
|
|
19232
19278
|
if (!span) return callback(childObservabilityContext);
|
|
19233
|
-
return span.executeInContext(() =>
|
|
19279
|
+
return span.executeInContext(async () => {
|
|
19280
|
+
try {
|
|
19281
|
+
const result = await callback(childObservabilityContext);
|
|
19282
|
+
span.end();
|
|
19283
|
+
return result;
|
|
19284
|
+
} catch (error) {
|
|
19285
|
+
span.error({
|
|
19286
|
+
error,
|
|
19287
|
+
endSpan: true
|
|
19288
|
+
});
|
|
19289
|
+
throw error;
|
|
19290
|
+
}
|
|
19291
|
+
});
|
|
19234
19292
|
}
|
|
19235
19293
|
//#endregion
|
|
19236
19294
|
//#region src/processors/observational-memory/observer-runner.ts
|
|
@@ -19368,13 +19426,13 @@ var ObserverRunner = class {
|
|
|
19368
19426
|
let parsed = parseObserverOutput(result.text, activeExtractors);
|
|
19369
19427
|
let retriedDueToDegenerate = false;
|
|
19370
19428
|
if (parsed.degenerate) {
|
|
19371
|
-
omDebug(`[OM:callObserver] degenerate repetition detected, retrying once`);
|
|
19429
|
+
omDebug(`[OM:callObserver] degenerate repetition detected, retrying once. ${describeDegenerateOutput(result.text, 2e3)}`);
|
|
19372
19430
|
result = await doGenerate();
|
|
19373
19431
|
parsed = parseObserverOutput(result.text, activeExtractors);
|
|
19374
19432
|
retriedDueToDegenerate = true;
|
|
19375
19433
|
if (parsed.degenerate) {
|
|
19376
|
-
omDebug(`[OM:callObserver] degenerate repetition on retry, failing`);
|
|
19377
|
-
throw new Error(
|
|
19434
|
+
omDebug(`[OM:callObserver] degenerate repetition on retry, failing. ${describeDegenerateOutput(result.text, 2e3)}`);
|
|
19435
|
+
throw new Error(`Observer produced degenerate output after retry. ${describeDegenerateOutput(result.text)}`);
|
|
19378
19436
|
}
|
|
19379
19437
|
}
|
|
19380
19438
|
const structuredExtraction = await extractStructuredValues({
|
|
@@ -19518,13 +19576,13 @@ var ObserverRunner = class {
|
|
|
19518
19576
|
let parsed = parseMultiThreadObserverOutput(result.text, activeExtractors);
|
|
19519
19577
|
let retriedDueToDegenerate = false;
|
|
19520
19578
|
if (parsed.degenerate) {
|
|
19521
|
-
omDebug(`[OM:callMultiThreadObserver] degenerate repetition detected, retrying once`);
|
|
19579
|
+
omDebug(`[OM:callMultiThreadObserver] degenerate repetition detected, retrying once. ${describeDegenerateOutput(result.text, 2e3)}`);
|
|
19522
19580
|
result = await doGenerate();
|
|
19523
19581
|
parsed = parseMultiThreadObserverOutput(result.text, activeExtractors);
|
|
19524
19582
|
retriedDueToDegenerate = true;
|
|
19525
19583
|
if (parsed.degenerate) {
|
|
19526
|
-
omDebug(`[OM:callMultiThreadObserver] degenerate repetition on retry, failing`);
|
|
19527
|
-
throw new Error(
|
|
19584
|
+
omDebug(`[OM:callMultiThreadObserver] degenerate repetition on retry, failing. ${describeDegenerateOutput(result.text, 2e3)}`);
|
|
19585
|
+
throw new Error(`Multi-thread observer produced degenerate output after retry. ${describeDegenerateOutput(result.text)}`);
|
|
19528
19586
|
}
|
|
19529
19587
|
}
|
|
19530
19588
|
const structuredExtractionByThread = /* @__PURE__ */ new Map();
|
|
@@ -24367,10 +24425,11 @@ ObservationStrategy.create = ((om, opts) => {
|
|
|
24367
24425
|
});
|
|
24368
24426
|
//#endregion
|
|
24369
24427
|
//#region src/processors/observational-memory/observation-turn/load-memory-context.ts
|
|
24370
|
-
async function loadMemoryContextMessages({ memory, messageList, threadId, resourceId }) {
|
|
24428
|
+
async function loadMemoryContextMessages({ memory, messageList, threadId, resourceId, runState }) {
|
|
24371
24429
|
const ctx = await memory.getContext({
|
|
24372
24430
|
threadId,
|
|
24373
|
-
resourceId
|
|
24431
|
+
resourceId,
|
|
24432
|
+
runState
|
|
24374
24433
|
});
|
|
24375
24434
|
for (const msg of ctx.messages) if (msg.role !== "system") messageList.add(msg, "memory");
|
|
24376
24435
|
return ctx;
|
|
@@ -24828,10 +24887,11 @@ var ObservationTurn = class {
|
|
|
24828
24887
|
* If a MemoryContextProvider is passed, loads historical messages and adds
|
|
24829
24888
|
* them to the MessageList. Without a provider, only fetches/caches the record.
|
|
24830
24889
|
*/
|
|
24831
|
-
async start(memory) {
|
|
24890
|
+
async start(memory, runState) {
|
|
24832
24891
|
if (this._started) throw new Error("Turn already started");
|
|
24833
24892
|
this._started = true;
|
|
24834
24893
|
this._record = await this.om.getOrCreateRecord(this.threadId, this.resourceId);
|
|
24894
|
+
runState?.set(`observational-memory:record:${this.threadId}:${this.resourceId ?? ""}`, this._record);
|
|
24835
24895
|
this._generationCountAtStart = this._record.generationCount;
|
|
24836
24896
|
this.memory = memory;
|
|
24837
24897
|
if (memory) {
|
|
@@ -24839,7 +24899,8 @@ var ObservationTurn = class {
|
|
|
24839
24899
|
memory,
|
|
24840
24900
|
messageList: this.messageList,
|
|
24841
24901
|
threadId: this.threadId,
|
|
24842
|
-
resourceId: this.resourceId
|
|
24902
|
+
resourceId: this.resourceId,
|
|
24903
|
+
runState
|
|
24843
24904
|
});
|
|
24844
24905
|
this._context = {
|
|
24845
24906
|
messages: ctx.messages,
|
|
@@ -25467,7 +25528,7 @@ var ReflectorRunner = class {
|
|
|
25467
25528
|
finalProviderMetadata = result.providerMetadata ?? finalProviderMetadata;
|
|
25468
25529
|
parsed = parseReflectorOutput(result.text, observations, activeExtractors);
|
|
25469
25530
|
if (parsed.degenerate) {
|
|
25470
|
-
omDebug(`[OM:callReflector] attempt #${attemptNumber}: degenerate repetition detected, treating as compression failure`);
|
|
25531
|
+
omDebug(`[OM:callReflector] attempt #${attemptNumber}: degenerate repetition detected, treating as compression failure. ${describeDegenerateOutput(result.text, 2e3)}`);
|
|
25471
25532
|
reflectedTokens = originalTokens;
|
|
25472
25533
|
} else reflectedTokens = this.tokenCounter.countObservations(parsed.observations);
|
|
25473
25534
|
omDebug(`[OM:callReflector] attempt #${attemptNumber} parsed: reflectedTokens=${reflectedTokens}, targetThreshold=${targetThreshold}, compressionValid=${validateCompression(reflectedTokens, targetThreshold)}, parsedObsLen=${parsed.observations?.length}, degenerate=${parsed.degenerate ?? false}`);
|
|
@@ -28921,7 +28982,9 @@ var ObservationalMemoryProcessor = class {
|
|
|
28921
28982
|
return messageList;
|
|
28922
28983
|
}
|
|
28923
28984
|
const { threadId, resourceId } = context;
|
|
28924
|
-
const
|
|
28985
|
+
const memoryContext = (0, _mastra_core_memory.parseMemoryRequestContext)(requestContext);
|
|
28986
|
+
const runState = memoryContext?.runState?.();
|
|
28987
|
+
const readOnly = memoryContext?.memoryConfig?.readOnly;
|
|
28925
28988
|
const actorModelContext = model?.modelId ? {
|
|
28926
28989
|
provider: model.provider,
|
|
28927
28990
|
modelId: model.modelId,
|
|
@@ -28938,7 +29001,8 @@ var ObservationalMemoryProcessor = class {
|
|
|
28938
29001
|
memory: this.memory,
|
|
28939
29002
|
messageList,
|
|
28940
29003
|
threadId,
|
|
28941
|
-
resourceId
|
|
29004
|
+
resourceId,
|
|
29005
|
+
runState
|
|
28942
29006
|
});
|
|
28943
29007
|
const systemMessages = ctx.omRecord ? await this.engine.buildContextSystemMessages({
|
|
28944
29008
|
threadId,
|
|
@@ -28979,7 +29043,7 @@ var ObservationalMemoryProcessor = class {
|
|
|
28979
29043
|
this.turn.sendStateSignal = args.sendStateSignal;
|
|
28980
29044
|
this.turn.agent = args.agent;
|
|
28981
29045
|
this.turn.requestContext = requestContext;
|
|
28982
|
-
await this.turn.start(this.memory);
|
|
29046
|
+
await this.turn.start(this.memory, runState);
|
|
28983
29047
|
if (stepNumber === 0 && this.temporalMarkers) await insertTemporalGapMarkers({
|
|
28984
29048
|
messageList,
|
|
28985
29049
|
sendSignal: args.sendSignal
|
|
@@ -30149,14 +30213,18 @@ ${workingMemory}`;
|
|
|
30149
30213
|
if (!this.threadConfig.workingMemory?.enabled) return null;
|
|
30150
30214
|
return extractWorkingMemoryContent(text)?.trim() ?? null;
|
|
30151
30215
|
}
|
|
30152
|
-
async getWorkingMemory({ threadId, resourceId, memoryConfig }) {
|
|
30216
|
+
async getWorkingMemory({ threadId, resourceId, memoryConfig, runState }) {
|
|
30153
30217
|
const config = this.getMergedThreadConfig(memoryConfig || {});
|
|
30154
30218
|
if (!config.workingMemory?.enabled) return null;
|
|
30155
30219
|
const scope = config.workingMemory.scope || "resource";
|
|
30156
30220
|
let workingMemoryData = null;
|
|
30157
30221
|
if (scope === "resource" && !resourceId) throw new Error("Memory error: Resource-scoped working memory is enabled but no resourceId was provided. Either provide a resourceId or explicitly set workingMemory.scope to 'thread'.");
|
|
30158
|
-
if (scope === "resource" && resourceId)
|
|
30159
|
-
|
|
30222
|
+
if (scope === "resource" && resourceId) {
|
|
30223
|
+
const loadWorkingMemory = async () => {
|
|
30224
|
+
return (await (await this.getMemoryStore()).getResourceById({ resourceId }))?.workingMemory || null;
|
|
30225
|
+
};
|
|
30226
|
+
workingMemoryData = runState ? await runState.load(`working-memory:resource:${resourceId}`, loadWorkingMemory) : await loadWorkingMemory();
|
|
30227
|
+
} else workingMemoryData = (runState?.threadLoaded ? runState.thread : await this.getThreadById({ threadId }))?.metadata?.workingMemory;
|
|
30160
30228
|
if (!workingMemoryData) return null;
|
|
30161
30229
|
return workingMemoryData;
|
|
30162
30230
|
}
|
|
@@ -30188,16 +30256,18 @@ ${workingMemory}`;
|
|
|
30188
30256
|
content: (config.workingMemory.template || this.defaultWorkingMemoryTemplate).trim()
|
|
30189
30257
|
};
|
|
30190
30258
|
}
|
|
30191
|
-
async getSystemMessage({ threadId, resourceId, memoryConfig }) {
|
|
30259
|
+
async getSystemMessage({ threadId, resourceId, memoryConfig, runState }) {
|
|
30192
30260
|
const config = this.getMergedThreadConfig(memoryConfig);
|
|
30193
30261
|
this.assertWorkingMemoryStateSignalsCompatibility(config);
|
|
30194
30262
|
if (!config.workingMemory?.enabled) return null;
|
|
30195
30263
|
if (config.workingMemory?.useStateSignals) return null;
|
|
30196
|
-
const
|
|
30264
|
+
const loadTemplate = () => this.getWorkingMemoryTemplate({ memoryConfig });
|
|
30265
|
+
const workingMemoryTemplate = runState ? await runState.load("working-memory:template", loadTemplate) : await loadTemplate();
|
|
30197
30266
|
const workingMemoryData = await this.getWorkingMemory({
|
|
30198
30267
|
threadId,
|
|
30199
30268
|
resourceId,
|
|
30200
|
-
memoryConfig: config
|
|
30269
|
+
memoryConfig: config,
|
|
30270
|
+
runState
|
|
30201
30271
|
});
|
|
30202
30272
|
if (!workingMemoryTemplate) return null;
|
|
30203
30273
|
const workingMemoryConfig = config.workingMemory;
|
|
@@ -30230,7 +30300,7 @@ ${workingMemory}`;
|
|
|
30230
30300
|
* ```
|
|
30231
30301
|
*/
|
|
30232
30302
|
async getContext(opts) {
|
|
30233
|
-
const { threadId, resourceId, memoryConfig } = opts;
|
|
30303
|
+
const { threadId, resourceId, memoryConfig, runState } = opts;
|
|
30234
30304
|
const config = this.getMergedThreadConfig(memoryConfig);
|
|
30235
30305
|
const memoryStore = await this.getMemoryStore();
|
|
30236
30306
|
const systemParts = [];
|
|
@@ -30240,10 +30310,14 @@ ${workingMemory}`;
|
|
|
30240
30310
|
let otherThreadsContext;
|
|
30241
30311
|
const omEngine = await this.omEngine;
|
|
30242
30312
|
if (omEngine) {
|
|
30243
|
-
|
|
30313
|
+
const loadOmRecord = () => omEngine.getRecord(threadId, resourceId);
|
|
30314
|
+
omRecord = runState ? await runState.load(`observational-memory:record:${threadId}:${resourceId ?? ""}`, loadOmRecord) : await loadOmRecord();
|
|
30244
30315
|
if (omRecord?.activeObservations) {
|
|
30245
30316
|
hasObservations = true;
|
|
30246
|
-
if (omEngine.scope === "resource" && resourceId)
|
|
30317
|
+
if (omEngine.scope === "resource" && resourceId) {
|
|
30318
|
+
const loadOtherThreadsContext = () => omEngine.getOtherThreadsContext(resourceId, threadId);
|
|
30319
|
+
otherThreadsContext = runState ? await runState.load(`observational-memory:other-threads:${resourceId}:${threadId}:${omRecord.lastObservedAt ?? ""}`, loadOtherThreadsContext) : await loadOtherThreadsContext();
|
|
30320
|
+
}
|
|
30247
30321
|
const obsSystemMessage = await omEngine.buildContextSystemMessage({
|
|
30248
30322
|
threadId,
|
|
30249
30323
|
resourceId,
|
|
@@ -30271,30 +30345,41 @@ ${workingMemory}`;
|
|
|
30271
30345
|
const workingMemoryMessage = await this.getSystemMessage({
|
|
30272
30346
|
threadId,
|
|
30273
30347
|
resourceId,
|
|
30274
|
-
memoryConfig: config
|
|
30348
|
+
memoryConfig: config,
|
|
30349
|
+
runState
|
|
30275
30350
|
});
|
|
30276
30351
|
if (workingMemoryMessage) systemParts.push(workingMemoryMessage);
|
|
30277
30352
|
let messages;
|
|
30278
30353
|
if (omEngine && omRecord) {
|
|
30279
30354
|
const dateFilter = omRecord.lastObservedAt ? { dateRange: { start: new Date(new Date(omRecord.lastObservedAt).getTime() + 1) } } : void 0;
|
|
30280
|
-
|
|
30281
|
-
|
|
30282
|
-
|
|
30283
|
-
|
|
30284
|
-
|
|
30285
|
-
|
|
30286
|
-
|
|
30287
|
-
|
|
30288
|
-
|
|
30289
|
-
|
|
30290
|
-
|
|
30291
|
-
|
|
30292
|
-
|
|
30293
|
-
|
|
30294
|
-
|
|
30295
|
-
|
|
30296
|
-
|
|
30297
|
-
|
|
30355
|
+
const boundary = omRecord.lastObservedAt ? new Date(omRecord.lastObservedAt).toISOString() : "";
|
|
30356
|
+
if (omEngine.scope === "resource" && resourceId) {
|
|
30357
|
+
const loadMessages = async () => {
|
|
30358
|
+
return (await memoryStore.listMessagesByResourceId({
|
|
30359
|
+
resourceId,
|
|
30360
|
+
orderBy: {
|
|
30361
|
+
field: "createdAt",
|
|
30362
|
+
direction: "ASC"
|
|
30363
|
+
},
|
|
30364
|
+
perPage: false,
|
|
30365
|
+
filter: dateFilter
|
|
30366
|
+
})).messages;
|
|
30367
|
+
};
|
|
30368
|
+
messages = runState ? await runState.load(`observational-memory:messages:resource:${resourceId}:${boundary}`, loadMessages) : await loadMessages();
|
|
30369
|
+
} else {
|
|
30370
|
+
const loadMessages = async () => {
|
|
30371
|
+
return (await memoryStore.listMessages({
|
|
30372
|
+
threadId,
|
|
30373
|
+
orderBy: {
|
|
30374
|
+
field: "createdAt",
|
|
30375
|
+
direction: "ASC"
|
|
30376
|
+
},
|
|
30377
|
+
perPage: false,
|
|
30378
|
+
filter: dateFilter
|
|
30379
|
+
})).messages;
|
|
30380
|
+
};
|
|
30381
|
+
messages = runState ? await runState.load(`observational-memory:messages:thread:${threadId}:${boundary}`, loadMessages) : await loadMessages();
|
|
30382
|
+
}
|
|
30298
30383
|
} else {
|
|
30299
30384
|
const lastMessages = config.lastMessages;
|
|
30300
30385
|
if (lastMessages === false) messages = [];
|
|
@@ -31599,4 +31684,4 @@ Object.defineProperty(exports, "wrapInObservationGroup", {
|
|
|
31599
31684
|
}
|
|
31600
31685
|
});
|
|
31601
31686
|
|
|
31602
|
-
//# sourceMappingURL=src-
|
|
31687
|
+
//# sourceMappingURL=src-bE5dqCVp.cjs.map
|