@mastra/memory 1.30.0-alpha.2 → 1.30.0-alpha.4
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/docs/references/docs-guides-context-engineering.md +1 -1
- package/dist/docs/references/docs-memory-observational-memory.md +2 -2
- package/dist/docs/references/reference-memory-observational-memory.md +3 -2
- package/dist/index.cjs +1 -1
- 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/load-memory-context.d.ts.map +1 -1
- package/dist/processors/observational-memory/observation-turn/safe-buffer-prefix.d.ts +35 -0
- package/dist/processors/observational-memory/observation-turn/safe-buffer-prefix.d.ts.map +1 -0
- 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.map +1 -1
- package/dist/processors/observational-memory/processor.d.ts.map +1 -1
- package/dist/processors/observational-memory/tracing.d.ts.map +1 -1
- package/dist/processors/observational-memory/types.d.ts +6 -0
- package/dist/processors/observational-memory/types.d.ts.map +1 -1
- package/dist/{src-TN3MwGgP.js → src-Dt8oPiQN.js} +113 -36
- package/dist/src-Dt8oPiQN.js.map +1 -0
- package/dist/{src-Bs9_1MCb.cjs → src-oL_dDHN9.cjs} +113 -36
- package/dist/src-oL_dDHN9.cjs.map +1 -0
- package/package.json +4 -4
- package/dist/src-Bs9_1MCb.cjs.map +0 -1
- package/dist/src-TN3MwGgP.js.map +0 -1
|
@@ -19819,19 +19819,28 @@ const PHASE_CONFIG = {
|
|
|
19819
19819
|
};
|
|
19820
19820
|
async function withOmTracingSpan({ phase, model, inputTokens, requestContext, observabilityContext, metadata, callback }) {
|
|
19821
19821
|
const config = PHASE_CONFIG[phase];
|
|
19822
|
+
const tracingContext = observabilityContext?.tracingContext ?? observabilityContext?.tracing;
|
|
19823
|
+
const callerMetadata = tracingContext?.currentSpan?.metadata;
|
|
19824
|
+
const inheritedCallerThreadId = callerMetadata?.__mastraObservationalMemoryCallerThreadId;
|
|
19825
|
+
const callerThreadId = callerMetadata?.threadId;
|
|
19826
|
+
const requestThreadId = requestContext?.get(_mastra_core_request_context.MASTRA_THREAD_ID_KEY);
|
|
19827
|
+
const omCallerThreadId = typeof inheritedCallerThreadId === "string" && inheritedCallerThreadId ? inheritedCallerThreadId : typeof callerThreadId === "string" && callerThreadId ? callerThreadId : typeof requestThreadId === "string" && requestThreadId ? requestThreadId : void 0;
|
|
19822
19828
|
const span = (0, _mastra_core_observability.getOrCreateSpan)({
|
|
19823
19829
|
type: _mastra_core_observability.SpanType.MEMORY_OPERATION,
|
|
19824
19830
|
name: config.name,
|
|
19825
19831
|
entityType: _mastra_core_observability.EntityType.MEMORY,
|
|
19826
19832
|
entityName: config.entityName,
|
|
19827
|
-
tracingContext
|
|
19833
|
+
tracingContext,
|
|
19828
19834
|
attributes: {
|
|
19829
19835
|
operationType: config.operationType,
|
|
19830
19836
|
inputTokens,
|
|
19831
19837
|
selectedModel: typeof model === "string" ? model : "(dynamic-model)",
|
|
19832
19838
|
...config.multiThread ? { multiThread: true } : {}
|
|
19833
19839
|
},
|
|
19834
|
-
metadata
|
|
19840
|
+
metadata: omCallerThreadId !== void 0 ? {
|
|
19841
|
+
...metadata,
|
|
19842
|
+
__mastraObservationalMemoryCallerThreadId: omCallerThreadId
|
|
19843
|
+
} : metadata,
|
|
19835
19844
|
requestContext
|
|
19836
19845
|
});
|
|
19837
19846
|
const childObservabilityContext = (0, _mastra_core_observability.createObservabilityContext)({ currentSpan: span });
|
|
@@ -25279,10 +25288,61 @@ async function loadMemoryContextMessages({ memory, messageList, threadId, resour
|
|
|
25279
25288
|
resourceId,
|
|
25280
25289
|
runState
|
|
25281
25290
|
});
|
|
25282
|
-
|
|
25291
|
+
const existingIds = new Set(messageList.get.all.db().map((message) => message.id));
|
|
25292
|
+
for (const msg of ctx.messages) if (msg.role !== "system" && !existingIds.has(msg.id)) messageList.add(msg, "memory");
|
|
25283
25293
|
return ctx;
|
|
25284
25294
|
}
|
|
25285
25295
|
//#endregion
|
|
25296
|
+
//#region src/processors/observational-memory/observation-turn/safe-buffer-prefix.ts
|
|
25297
|
+
function hasPendingToolCall(message) {
|
|
25298
|
+
return message.content.parts?.some((part) => part.type === "tool-invocation" && part.toolInvocation.state === "call") ?? false;
|
|
25299
|
+
}
|
|
25300
|
+
/**
|
|
25301
|
+
* Selects the unobserved messages that are safe to buffer while a tool call
|
|
25302
|
+
* may still be in flight.
|
|
25303
|
+
*
|
|
25304
|
+
* Only the chronologically last candidate can hold a live pending call: a
|
|
25305
|
+
* `tool-invocation` still in state `call` (client- or provider-executed) on the
|
|
25306
|
+
* newest message means the request ended waiting for its result. Any earlier
|
|
25307
|
+
* `call` is an orphan — the conversation already continued past it, and core's
|
|
25308
|
+
* output converter drops or placeholder-pairs it before the prompt reaches a
|
|
25309
|
+
* provider — so it is buffered like any other message.
|
|
25310
|
+
*
|
|
25311
|
+
* When the last candidate is pending, the prefix before it is buffered, but only
|
|
25312
|
+
* when the cut is clean. The cut is unsafe — and the whole attempt is deferred —
|
|
25313
|
+
* when:
|
|
25314
|
+
*
|
|
25315
|
+
* - Cursor collision: buffering advances the persisted cursor to
|
|
25316
|
+
* `max(buffered.createdAt) + 1ms`, and later candidate selection requires
|
|
25317
|
+
* `createdAt > cursor`. If the retained message sits at the same or +1ms
|
|
25318
|
+
* timestamp, the cursor would permanently hide it even after its result
|
|
25319
|
+
* arrives.
|
|
25320
|
+
* - Split tool exchange: a `toolCallId` appears on both sides of the cut, so
|
|
25321
|
+
* the observer would see half of a tool exchange.
|
|
25322
|
+
* - Ambiguous tail: several candidates share the newest timestamp and one of
|
|
25323
|
+
* them holds a pending call. `createdAt` alone cannot say which is really
|
|
25324
|
+
* last, so the pending call is treated as the tail and the attempt deferred.
|
|
25325
|
+
*
|
|
25326
|
+
* The result is always in chronological order. When the tail has no pending
|
|
25327
|
+
* call, every message is returned. An empty result means "defer this buffering
|
|
25328
|
+
* attempt" — callers must skip buffering entirely. Raw message persistence is
|
|
25329
|
+
* unaffected and happens elsewhere; the retained message becomes eligible again
|
|
25330
|
+
* once its tool call completes.
|
|
25331
|
+
*/
|
|
25332
|
+
function selectSafeBufferPrefix(messages) {
|
|
25333
|
+
const chronological = [...messages].sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
|
|
25334
|
+
const last = chronological[chronological.length - 1];
|
|
25335
|
+
if (!last) return chronological;
|
|
25336
|
+
const newestTime = new Date(last.createdAt).getTime();
|
|
25337
|
+
const newestGroup = chronological.filter((message) => new Date(message.createdAt).getTime() === newestTime);
|
|
25338
|
+
if (!newestGroup.some(hasPendingToolCall)) return chronological;
|
|
25339
|
+
if (newestGroup.length > 1) return [];
|
|
25340
|
+
const prefix = chronological.slice(0, -1);
|
|
25341
|
+
const retainedTime = new Date(last.createdAt).getTime();
|
|
25342
|
+
const retainedToolIds = new Set((last.content.parts ?? []).flatMap((part) => part.type === "tool-invocation" ? [part.toolInvocation.toolCallId] : []));
|
|
25343
|
+
return prefix.some((message) => new Date(message.createdAt).getTime() + 1 >= retainedTime || message.content.parts?.some((part) => part.type === "tool-invocation" && retainedToolIds.has(part.toolInvocation.toolCallId))) ? [] : prefix;
|
|
25344
|
+
}
|
|
25345
|
+
//#endregion
|
|
25286
25346
|
//#region src/processors/observational-memory/observation-turn/step.ts
|
|
25287
25347
|
/**
|
|
25288
25348
|
* Represents a single step in the agentic loop within an observation turn.
|
|
@@ -25405,37 +25465,41 @@ var ObservationStep = class {
|
|
|
25405
25465
|
record: this.turn.record,
|
|
25406
25466
|
messages: getObservableMessages(messageList)
|
|
25407
25467
|
});
|
|
25408
|
-
if (statusSnapshot.shouldBuffer
|
|
25468
|
+
if (statusSnapshot.shouldBuffer) {
|
|
25409
25469
|
const allMessages = getObservableMessages(messageList);
|
|
25410
25470
|
const unobservedMessages = om.getUnobservedMessages(allMessages, statusSnapshot.record);
|
|
25411
25471
|
const candidates = om.getUnobservedMessages(unobservedMessages, statusSnapshot.record, { excludeBuffered: true });
|
|
25412
|
-
|
|
25413
|
-
|
|
25472
|
+
const safeCandidates = selectSafeBufferPrefix(candidates);
|
|
25473
|
+
const deferred = candidates.length > 0 && safeCandidates.length === 0;
|
|
25474
|
+
if (safeCandidates.length > 0) {
|
|
25475
|
+
om.sealMessagesForBuffering(safeCandidates);
|
|
25414
25476
|
try {
|
|
25415
25477
|
await this.turn.hooks?.onBufferChunkSealed?.();
|
|
25416
25478
|
} catch (error) {
|
|
25417
25479
|
omDebug(`[OM:buffer] onBufferChunkSealed hook failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
25418
25480
|
}
|
|
25419
|
-
if (this.turn.memory) await this.turn.memory.persistMessages(
|
|
25420
|
-
messageList.removeByIds(
|
|
25421
|
-
for (const msg of
|
|
25481
|
+
if (this.turn.memory) await this.turn.memory.persistMessages(safeCandidates);
|
|
25482
|
+
messageList.removeByIds(safeCandidates.map((msg) => msg.id));
|
|
25483
|
+
for (const msg of safeCandidates) messageList.add(msg, "memory");
|
|
25484
|
+
}
|
|
25485
|
+
if (!deferred) {
|
|
25486
|
+
om.trackBackgroundWork(om.buffer({
|
|
25487
|
+
threadId,
|
|
25488
|
+
resourceId,
|
|
25489
|
+
messages: safeCandidates,
|
|
25490
|
+
pendingTokens: statusSnapshot.pendingTokens,
|
|
25491
|
+
record: statusSnapshot.record,
|
|
25492
|
+
writer: this.turn.writer,
|
|
25493
|
+
agent: this.turn.agent,
|
|
25494
|
+
sendSignal: this.turn.sendSignal,
|
|
25495
|
+
sendStateSignal: this.turn.sendStateSignal,
|
|
25496
|
+
requestContext: this.turn.requestContext,
|
|
25497
|
+
observabilityContext: this.turn.observabilityContext
|
|
25498
|
+
}).catch((err) => {
|
|
25499
|
+
omDebug(`[OM:buffer] fire-and-forget buffer failed: ${err?.message}`);
|
|
25500
|
+
}));
|
|
25501
|
+
buffered = true;
|
|
25422
25502
|
}
|
|
25423
|
-
om.trackBackgroundWork(om.buffer({
|
|
25424
|
-
threadId,
|
|
25425
|
-
resourceId,
|
|
25426
|
-
messages: unobservedMessages,
|
|
25427
|
-
pendingTokens: statusSnapshot.pendingTokens,
|
|
25428
|
-
record: statusSnapshot.record,
|
|
25429
|
-
writer: this.turn.writer,
|
|
25430
|
-
agent: this.turn.agent,
|
|
25431
|
-
sendSignal: this.turn.sendSignal,
|
|
25432
|
-
sendStateSignal: this.turn.sendStateSignal,
|
|
25433
|
-
requestContext: this.turn.requestContext,
|
|
25434
|
-
observabilityContext: this.turn.observabilityContext
|
|
25435
|
-
}).catch((err) => {
|
|
25436
|
-
omDebug(`[OM:buffer] fire-and-forget buffer failed: ${err?.message}`);
|
|
25437
|
-
}));
|
|
25438
|
-
buffered = true;
|
|
25439
25503
|
}
|
|
25440
25504
|
const willObserveNow = statusSnapshot.shouldObserve && !hasIncompleteToolCalls;
|
|
25441
25505
|
/** In-flight message ids the step-0 cleanup must never remove from live context. */
|
|
@@ -25810,11 +25874,11 @@ var ObservationTurn = class {
|
|
|
25810
25874
|
if (asyncObservationEnabled && bufferOnIdle) {
|
|
25811
25875
|
const allMessages = getObservableMessages(this.messageList);
|
|
25812
25876
|
const record = this._record;
|
|
25813
|
-
const
|
|
25814
|
-
if (
|
|
25877
|
+
const idleMessages = selectSafeBufferPrefix(this.om.getUnobservedMessages(allMessages, record));
|
|
25878
|
+
if (idleMessages.length > 0) this.om.trackBackgroundWork(this.om.buffer({
|
|
25815
25879
|
threadId: this.threadId,
|
|
25816
25880
|
resourceId: this.resourceId,
|
|
25817
|
-
messages:
|
|
25881
|
+
messages: idleMessages,
|
|
25818
25882
|
record,
|
|
25819
25883
|
writer: this.writer,
|
|
25820
25884
|
agent: this.agent,
|
|
@@ -27542,15 +27606,18 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
27542
27606
|
this.hookExecution = config.hookExecution ?? "non-blocking";
|
|
27543
27607
|
this.mastra = config.mastra;
|
|
27544
27608
|
this.memory = config.memory;
|
|
27609
|
+
const topLevelModel = config.model;
|
|
27610
|
+
const observationConfigModel = config.observation?.model;
|
|
27611
|
+
const reflectionConfigModel = config.reflection?.model;
|
|
27545
27612
|
const resolveModel = (model, defaultModel) => model === "default" ? defaultModel : model;
|
|
27546
|
-
const observationModel = resolveModel(
|
|
27547
|
-
const reflectionModel = resolveModel(
|
|
27613
|
+
const observationModel = resolveModel(topLevelModel, OBSERVATIONAL_MEMORY_DEFAULTS.observation.model) ?? resolveModel(observationConfigModel, OBSERVATIONAL_MEMORY_DEFAULTS.observation.model) ?? resolveModel(reflectionConfigModel, OBSERVATIONAL_MEMORY_DEFAULTS.observation.model) ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.model;
|
|
27614
|
+
const reflectionModel = resolveModel(topLevelModel, OBSERVATIONAL_MEMORY_DEFAULTS.reflection.model) ?? resolveModel(reflectionConfigModel, OBSERVATIONAL_MEMORY_DEFAULTS.reflection.model) ?? resolveModel(observationConfigModel, OBSERVATIONAL_MEMORY_DEFAULTS.reflection.model) ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.model;
|
|
27548
27615
|
const messageTokens = config.observation?.messageTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.messageTokens;
|
|
27549
27616
|
const observationTokens = config.reflection?.observationTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.observationTokens;
|
|
27550
27617
|
const isSharedBudget = config.shareTokenBudget ?? false;
|
|
27551
27618
|
const isDefaultModelSelection = (model) => model === void 0 || model === "default" || model instanceof ModelByInputTokens;
|
|
27552
|
-
const observationSelectedModel =
|
|
27553
|
-
const reflectionSelectedModel =
|
|
27619
|
+
const observationSelectedModel = topLevelModel ?? observationConfigModel ?? reflectionConfigModel;
|
|
27620
|
+
const reflectionSelectedModel = topLevelModel ?? reflectionConfigModel ?? observationConfigModel;
|
|
27554
27621
|
const observationDefaultMaxOutputTokens = config.observation?.modelSettings?.maxOutputTokens ?? (isDefaultModelSelection(observationSelectedModel) ? OBSERVATIONAL_MEMORY_DEFAULTS.observation.modelSettings.maxOutputTokens : void 0);
|
|
27555
27622
|
const reflectionDefaultMaxOutputTokens = config.reflection?.modelSettings?.maxOutputTokens ?? (isDefaultModelSelection(reflectionSelectedModel) ? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.modelSettings.maxOutputTokens : void 0);
|
|
27556
27623
|
const totalBudget = messageTokens + observationTokens;
|
|
@@ -28513,7 +28580,7 @@ ${formattedMessages}
|
|
|
28513
28580
|
if (!this.buffering.isAsyncObservationEnabled()) return false;
|
|
28514
28581
|
const lockKey = this.buffering.getLockKey(opts.threadId, opts.resourceId);
|
|
28515
28582
|
const shouldTrigger = this.buffering.shouldTriggerAsyncObservation(opts.pendingTokens, lockKey, opts.record, this.storage, opts.threshold);
|
|
28516
|
-
if (shouldTrigger) this.trackBackgroundWork(this.startAsyncBufferedObservation(opts.record, opts.threadId, opts.unobservedMessages, lockKey, opts.writer, opts.unbufferedPendingTokens, opts.requestContext));
|
|
28583
|
+
if (shouldTrigger) this.trackBackgroundWork(this.startAsyncBufferedObservation(opts.record, opts.threadId, opts.unobservedMessages, lockKey, opts.writer, opts.unbufferedPendingTokens, opts.requestContext, opts.observabilityContext));
|
|
28517
28584
|
return shouldTrigger;
|
|
28518
28585
|
}
|
|
28519
28586
|
isMessageList(value) {
|
|
@@ -30270,6 +30337,16 @@ function normalizeObservationalMemoryConfig(config) {
|
|
|
30270
30337
|
if (typeof config === "object" && config.enabled === false) return void 0;
|
|
30271
30338
|
return config;
|
|
30272
30339
|
}
|
|
30340
|
+
/**
|
|
30341
|
+
* Observer model selection (`observation.model`, else top-level `model`), read into the widened
|
|
30342
|
+
* model type first: combining values of the public type makes TS subtype-reduce the model-id
|
|
30343
|
+
* literal union, which fails with TS2590 once the provider registry is large enough.
|
|
30344
|
+
*/
|
|
30345
|
+
function selectObserverModel(omConfig) {
|
|
30346
|
+
const observationModel = omConfig.observation?.model;
|
|
30347
|
+
const topLevelModel = omConfig.model;
|
|
30348
|
+
return observationModel ?? topLevelModel;
|
|
30349
|
+
}
|
|
30273
30350
|
function hasWorkingMemoryExtractor(extractors) {
|
|
30274
30351
|
return !!extractors?.some((extractor) => extractor.slug === "working-memory");
|
|
30275
30352
|
}
|
|
@@ -30387,7 +30464,7 @@ var Memory = class Memory extends _mastra_core_memory.MastraMemory {
|
|
|
30387
30464
|
const extract = observation.extract ?? [];
|
|
30388
30465
|
const existingSlugs = new Set(extract.map((extractor) => extractor.slug));
|
|
30389
30466
|
let curatorMemory;
|
|
30390
|
-
const subconsciousExtractors = omConfig.experimental_subconscious.createObservationExtractors(
|
|
30467
|
+
const subconsciousExtractors = omConfig.experimental_subconscious.createObservationExtractors(selectObserverModel(omConfig), () => curatorMemory ??= new Memory({
|
|
30391
30468
|
storage: this.storage,
|
|
30392
30469
|
options: { observationalMemory: false }
|
|
30393
30470
|
})).filter((extractor) => !existingSlugs.has(extractor.slug));
|
|
@@ -31693,7 +31770,7 @@ Notes:
|
|
|
31693
31770
|
if (remind && "builtIn" in remind) tools.ask_memory = createAskMemoryTool({
|
|
31694
31771
|
memory: this,
|
|
31695
31772
|
config: remind,
|
|
31696
|
-
omModel: omConfig
|
|
31773
|
+
omModel: selectObserverModel(omConfig),
|
|
31697
31774
|
getParentAgent: (agentId) => this._mastraInstance?.getAgentById(agentId)
|
|
31698
31775
|
});
|
|
31699
31776
|
}
|
|
@@ -32653,4 +32730,4 @@ Object.defineProperty(exports, "wrapInObservationGroup", {
|
|
|
32653
32730
|
}
|
|
32654
32731
|
});
|
|
32655
32732
|
|
|
32656
|
-
//# sourceMappingURL=src-
|
|
32733
|
+
//# sourceMappingURL=src-oL_dDHN9.cjs.map
|