@mastra/memory 1.31.0-alpha.0 → 1.31.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/dist/_types/@internal_ai-sdk-v4/package.json +1 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-memory-observational-memory.md +33 -0
- package/dist/docs/references/reference-memory-observational-memory.md +34 -4
- package/dist/hooks.cjs +158 -0
- package/dist/hooks.cjs.map +1 -0
- package/dist/hooks.d.ts +25 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +156 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +8 -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/hooks.d.ts +63 -0
- package/dist/processors/observational-memory/hooks.d.ts.map +1 -0
- package/dist/processors/observational-memory/observation-groups.d.ts.map +1 -1
- package/dist/processors/observational-memory/observation-strategies/async-buffer.d.ts.map +1 -1
- package/dist/processors/observational-memory/observation-strategies/resource-scoped.d.ts.map +1 -1
- package/dist/processors/observational-memory/observation-strategies/sync.d.ts.map +1 -1
- package/dist/processors/observational-memory/observation-strategies/thread-title.d.ts +15 -0
- package/dist/processors/observational-memory/observation-strategies/thread-title.d.ts.map +1 -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/types.d.ts +6 -6
- package/dist/{src-Da7AKXPR.cjs → src-C4niho1P.cjs} +206 -54
- package/dist/src-C4niho1P.cjs.map +1 -0
- package/dist/{src-DqLGJfSb.js → src-DquR-jTR.js} +208 -56
- package/dist/src-DquR-jTR.js.map +1 -0
- package/dist/tools/om-tools.d.ts +4 -2
- package/dist/tools/om-tools.d.ts.map +1 -1
- package/package.json +15 -5
- package/dist/src-Da7AKXPR.cjs.map +0 -1
- package/dist/src-DqLGJfSb.js.map +0 -1
|
@@ -22800,13 +22800,13 @@ function renderFormattedParts(parts, timestamps, options) {
|
|
|
22800
22800
|
tokenOffset: expandedTokens - options.maxTokens
|
|
22801
22801
|
};
|
|
22802
22802
|
}
|
|
22803
|
-
async function recallPart({ memory, threadId, resourceId, cursor, partIndex, charOffset, threadScope, maxTokens = DEFAULT_MAX_RESULT_TOKENS }) {
|
|
22803
|
+
async function recallPart({ memory, threadId, resourceId, cursor, partIndex, charOffset, threadScope, retrievalScope = "thread", maxTokens = DEFAULT_MAX_RESULT_TOKENS }) {
|
|
22804
22804
|
if (!memory || typeof memory.getMemoryStore !== "function") throw new Error("Memory instance is required for recall");
|
|
22805
22805
|
if (!threadId) throw new Error("Thread ID is required for recall");
|
|
22806
22806
|
const resolved = await resolveCursorMessage(memory, cursor, {
|
|
22807
22807
|
resourceId,
|
|
22808
22808
|
threadScope,
|
|
22809
|
-
enforceThreadScope:
|
|
22809
|
+
enforceThreadScope: retrievalScope !== "resource"
|
|
22810
22810
|
});
|
|
22811
22811
|
if ("hint" in resolved) throw new Error(resolved.hint);
|
|
22812
22812
|
const allParts = formatMessageParts(resolved, "high");
|
|
@@ -22817,7 +22817,7 @@ async function recallPart({ memory, threadId, resourceId, cursor, partIndex, cha
|
|
|
22817
22817
|
if (partIndex > Math.max(...allParts.map((p) => p.partIndex))) {
|
|
22818
22818
|
const nextMessage = await getNextVisibleMessage({
|
|
22819
22819
|
memory,
|
|
22820
|
-
threadId,
|
|
22820
|
+
threadId: resolved.threadId ?? threadId,
|
|
22821
22821
|
resourceId,
|
|
22822
22822
|
after: resolved.createdAt
|
|
22823
22823
|
});
|
|
@@ -22856,7 +22856,7 @@ async function recallPart({ memory, threadId, resourceId, cursor, partIndex, cha
|
|
|
22856
22856
|
note
|
|
22857
22857
|
};
|
|
22858
22858
|
}
|
|
22859
|
-
async function recallMessages({ memory, threadId, resourceId, cursor, page = 1, limit = 20, detail = "low", partType, toolName, threadScope, maxTokens = DEFAULT_MAX_RESULT_TOKENS }) {
|
|
22859
|
+
async function recallMessages({ memory, threadId, resourceId, cursor, page = 1, limit = 20, detail = "low", partType, toolName, threadScope, retrievalScope = "thread", maxTokens = DEFAULT_MAX_RESULT_TOKENS }) {
|
|
22860
22860
|
if (!memory) throw new Error("Memory instance is required for recall");
|
|
22861
22861
|
if (!threadId) throw new Error("Thread ID is required for recall");
|
|
22862
22862
|
if (typeof memory.getMemoryStore !== "function") throw new Error("recall requires a Memory instance with storage access");
|
|
@@ -22867,7 +22867,7 @@ async function recallMessages({ memory, threadId, resourceId, cursor, page = 1,
|
|
|
22867
22867
|
const resolved = await resolveCursorMessage(memory, cursor, {
|
|
22868
22868
|
resourceId,
|
|
22869
22869
|
threadScope,
|
|
22870
|
-
enforceThreadScope:
|
|
22870
|
+
enforceThreadScope: retrievalScope === "thread"
|
|
22871
22871
|
});
|
|
22872
22872
|
if ("hint" in resolved) return {
|
|
22873
22873
|
messages: resolved.hint,
|
|
@@ -22884,7 +22884,7 @@ async function recallMessages({ memory, threadId, resourceId, cursor, page = 1,
|
|
|
22884
22884
|
const anchor = resolved;
|
|
22885
22885
|
const crossThreadId = anchor.threadId && anchor.threadId !== threadId ? anchor.threadId : void 0;
|
|
22886
22886
|
if (crossThreadId && threadScope) return {
|
|
22887
|
-
messages: `Cursor does not belong to the active thread. Expected thread "${threadId}" but cursor "${cursor}" belongs to "${anchor.threadId}". Pass threadId="${anchor.threadId}" to browse that thread
|
|
22887
|
+
messages: `Cursor does not belong to the active thread. Expected thread "${threadId}" but cursor "${cursor}" belongs to "${anchor.threadId}". Pass threadId="${anchor.threadId}" to browse that thread.`,
|
|
22888
22888
|
count: 0,
|
|
22889
22889
|
cursor,
|
|
22890
22890
|
page: normalizedPage,
|
|
@@ -23043,7 +23043,8 @@ async function recallThreadFromStart({ memory, threadId, resourceId, page = 1, l
|
|
|
23043
23043
|
};
|
|
23044
23044
|
}
|
|
23045
23045
|
const recallTool = (_memoryConfig, options) => {
|
|
23046
|
-
const
|
|
23046
|
+
const retrievalScope = options?.retrievalScope ?? "thread";
|
|
23047
|
+
const isResourceScope = retrievalScope === "resource";
|
|
23047
23048
|
const searchEnabled = options?.searchEnabled ?? true;
|
|
23048
23049
|
const description = isResourceScope ? `Browse conversation history. Use mode="threads" to list all threads for the current user. Use mode="messages" (default) to browse messages in the current thread or pass threadId to browse another thread in the active resource. When mode="messages" has no cursor or threadId, it defaults to the current thread and says so at the top of the result. If you pass only a cursor, it must belong to the current thread.${searchEnabled ? " Use mode=\"search\" to find messages by content across all threads." : ""}` : `Browse conversation history in the current thread. Use mode="messages" (default) to page through messages near a cursor.${searchEnabled ? " Use mode=\"search\" to find messages by content in this thread." : ""} Use mode="threads" to get the current thread's ID and title.`;
|
|
23049
23050
|
const modeEnum = searchEnabled ? [
|
|
@@ -23254,23 +23255,25 @@ const recallTool = (_memoryConfig, options) => {
|
|
|
23254
23255
|
if (partIndex !== void 0 && partIndex !== null) return recallPart({
|
|
23255
23256
|
memory,
|
|
23256
23257
|
threadId: targetThreadId,
|
|
23257
|
-
resourceId
|
|
23258
|
+
resourceId,
|
|
23258
23259
|
cursor,
|
|
23259
23260
|
partIndex,
|
|
23260
23261
|
charOffset,
|
|
23261
|
-
threadScope
|
|
23262
|
+
threadScope,
|
|
23263
|
+
retrievalScope
|
|
23262
23264
|
});
|
|
23263
23265
|
return recallMessages({
|
|
23264
23266
|
memory,
|
|
23265
23267
|
threadId: targetThreadId,
|
|
23266
|
-
resourceId
|
|
23268
|
+
resourceId,
|
|
23267
23269
|
cursor,
|
|
23268
23270
|
page,
|
|
23269
23271
|
limit,
|
|
23270
23272
|
detail: detail ?? "low",
|
|
23271
23273
|
partType,
|
|
23272
23274
|
toolName,
|
|
23273
|
-
threadScope
|
|
23275
|
+
threadScope,
|
|
23276
|
+
retrievalScope
|
|
23274
23277
|
});
|
|
23275
23278
|
}
|
|
23276
23279
|
});
|
|
@@ -24376,7 +24379,8 @@ function stripThreadTags(observations) {
|
|
|
24376
24379
|
}
|
|
24377
24380
|
//#endregion
|
|
24378
24381
|
//#region src/processors/observational-memory/observation-groups.ts
|
|
24379
|
-
const
|
|
24382
|
+
const OBSERVATION_GROUP_OPEN = "<observation-group";
|
|
24383
|
+
const OBSERVATION_GROUP_CLOSE = "</observation-group>";
|
|
24380
24384
|
const ATTRIBUTE_PATTERN = /([\w][\w-]*)="([^"]*)"/g;
|
|
24381
24385
|
const REFLECTION_GROUP_SPLIT_PATTERN = /^##\s+Group\s+/m;
|
|
24382
24386
|
function parseObservationGroupAttributes(attributeString) {
|
|
@@ -24387,6 +24391,81 @@ function parseObservationGroupAttributes(attributeString) {
|
|
|
24387
24391
|
}
|
|
24388
24392
|
return attributes;
|
|
24389
24393
|
}
|
|
24394
|
+
function isLineStart(observations, index) {
|
|
24395
|
+
return index === 0 || observations[index - 1] === "\n";
|
|
24396
|
+
}
|
|
24397
|
+
function scanObservationGroupTags(observations) {
|
|
24398
|
+
const tags = [];
|
|
24399
|
+
const incompleteOpenings = [];
|
|
24400
|
+
let cursor = 0;
|
|
24401
|
+
let closeFloor = 0;
|
|
24402
|
+
while (cursor < observations.length) {
|
|
24403
|
+
const start = observations.indexOf(OBSERVATION_GROUP_OPEN, cursor);
|
|
24404
|
+
if (start === -1) break;
|
|
24405
|
+
const attributesStart = start + 18;
|
|
24406
|
+
if (!/\s/.test(observations[attributesStart] ?? "")) {
|
|
24407
|
+
cursor = attributesStart;
|
|
24408
|
+
continue;
|
|
24409
|
+
}
|
|
24410
|
+
const openEnd = observations.indexOf(">", attributesStart);
|
|
24411
|
+
if (openEnd === -1) break;
|
|
24412
|
+
const closeStart = observations.indexOf(OBSERVATION_GROUP_CLOSE, Math.max(openEnd + 1, closeFloor));
|
|
24413
|
+
if (closeStart === -1) {
|
|
24414
|
+
if (isLineStart(observations, start)) incompleteOpenings.push({
|
|
24415
|
+
start,
|
|
24416
|
+
end: openEnd + 1
|
|
24417
|
+
});
|
|
24418
|
+
closeFloor = observations.length;
|
|
24419
|
+
cursor = openEnd + 1;
|
|
24420
|
+
continue;
|
|
24421
|
+
}
|
|
24422
|
+
const nestedStart = observations.indexOf(OBSERVATION_GROUP_OPEN, openEnd + 1);
|
|
24423
|
+
if (nestedStart !== -1 && nestedStart < closeStart && isLineStart(observations, nestedStart)) {
|
|
24424
|
+
incompleteOpenings.push({
|
|
24425
|
+
start,
|
|
24426
|
+
end: openEnd + 1
|
|
24427
|
+
});
|
|
24428
|
+
closeFloor = closeStart;
|
|
24429
|
+
cursor = nestedStart;
|
|
24430
|
+
continue;
|
|
24431
|
+
}
|
|
24432
|
+
tags.push({
|
|
24433
|
+
start,
|
|
24434
|
+
end: closeStart + 20,
|
|
24435
|
+
attributeString: observations.slice(attributesStart, openEnd),
|
|
24436
|
+
content: observations.slice(openEnd + 1, closeStart)
|
|
24437
|
+
});
|
|
24438
|
+
closeFloor = closeStart;
|
|
24439
|
+
cursor = closeStart + 20;
|
|
24440
|
+
}
|
|
24441
|
+
return {
|
|
24442
|
+
tags,
|
|
24443
|
+
incompleteOpenings
|
|
24444
|
+
};
|
|
24445
|
+
}
|
|
24446
|
+
function replaceObservationGroupTags(observations, replace) {
|
|
24447
|
+
const { tags, incompleteOpenings } = scanObservationGroupTags(observations);
|
|
24448
|
+
const parts = [];
|
|
24449
|
+
let cursor = 0;
|
|
24450
|
+
let openingIndex = 0;
|
|
24451
|
+
const skipIncompleteOpeningsBefore = (limit) => {
|
|
24452
|
+
while (openingIndex < incompleteOpenings.length && incompleteOpenings[openingIndex].start < limit) {
|
|
24453
|
+
const opening = incompleteOpenings[openingIndex];
|
|
24454
|
+
openingIndex++;
|
|
24455
|
+
if (opening.start < cursor) continue;
|
|
24456
|
+
parts.push(observations.slice(cursor, opening.start));
|
|
24457
|
+
cursor = opening.end;
|
|
24458
|
+
}
|
|
24459
|
+
};
|
|
24460
|
+
for (const tag of tags) {
|
|
24461
|
+
skipIncompleteOpeningsBefore(tag.start);
|
|
24462
|
+
parts.push(observations.slice(cursor, tag.start), replace(tag));
|
|
24463
|
+
cursor = tag.end;
|
|
24464
|
+
}
|
|
24465
|
+
skipIncompleteOpeningsBefore(Number.POSITIVE_INFINITY);
|
|
24466
|
+
parts.push(observations.slice(cursor));
|
|
24467
|
+
return parts.join("");
|
|
24468
|
+
}
|
|
24390
24469
|
function parseReflectionObservationGroupSections(content) {
|
|
24391
24470
|
const normalizedContent = content.trim();
|
|
24392
24471
|
if (!normalizedContent || !REFLECTION_GROUP_SPLIT_PATTERN.test(normalizedContent)) return [];
|
|
@@ -24411,9 +24490,8 @@ function wrapInObservationGroup(observations, range, id = generateAnchorId(), _s
|
|
|
24411
24490
|
function parseObservationGroups(observations) {
|
|
24412
24491
|
if (!observations) return [];
|
|
24413
24492
|
const groups = [];
|
|
24414
|
-
|
|
24415
|
-
|
|
24416
|
-
const attributes = parseObservationGroupAttributes(match[1] ?? "");
|
|
24493
|
+
for (const tag of scanObservationGroupTags(observations).tags) {
|
|
24494
|
+
const attributes = parseObservationGroupAttributes(tag.attributeString);
|
|
24417
24495
|
const id = attributes.id;
|
|
24418
24496
|
const range = attributes.range;
|
|
24419
24497
|
if (!id || !range) continue;
|
|
@@ -24421,54 +24499,96 @@ function parseObservationGroups(observations) {
|
|
|
24421
24499
|
id,
|
|
24422
24500
|
range,
|
|
24423
24501
|
kind: attributes.kind,
|
|
24424
|
-
content:
|
|
24502
|
+
content: tag.content.trim()
|
|
24425
24503
|
});
|
|
24426
24504
|
}
|
|
24427
24505
|
return groups;
|
|
24428
24506
|
}
|
|
24429
24507
|
function stripObservationGroups(observations) {
|
|
24430
24508
|
if (!observations) return observations;
|
|
24431
|
-
return observations
|
|
24509
|
+
return replaceObservationGroupTags(observations, (tag) => tag.content.trim()).replace(/\n{3,}/g, "\n\n").trim();
|
|
24432
24510
|
}
|
|
24433
24511
|
function getRangeSegments(range) {
|
|
24434
24512
|
return range.split(",").map((segment) => segment.trim()).filter(Boolean);
|
|
24435
24513
|
}
|
|
24514
|
+
function getRangeEndpoints(segment) {
|
|
24515
|
+
const parts = segment.split(":").map((part) => part.trim());
|
|
24516
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) return null;
|
|
24517
|
+
return {
|
|
24518
|
+
start: parts[0],
|
|
24519
|
+
end: parts[1]
|
|
24520
|
+
};
|
|
24521
|
+
}
|
|
24522
|
+
/**
|
|
24523
|
+
* `buildMessageRange` produces opaque UUID endpoints, so those segments cannot be ordered by value.
|
|
24524
|
+
* Spanning from the first start to the last end keeps reflected metadata bounded — the full segment
|
|
24525
|
+
* list is deliberately not preserved (#14791). Segments that are not `start:end` pairs are left as
|
|
24526
|
+
* they are rather than being joined into a fabricated span.
|
|
24527
|
+
*/
|
|
24528
|
+
function spanRangeSegments(segments) {
|
|
24529
|
+
const endpoints = segments.map(getRangeEndpoints);
|
|
24530
|
+
if (endpoints.some((endpoint) => endpoint === null)) return segments.join(",");
|
|
24531
|
+
const first = endpoints[0];
|
|
24532
|
+
const last = endpoints.at(-1);
|
|
24533
|
+
return `${first.start}:${last.end}`;
|
|
24534
|
+
}
|
|
24436
24535
|
function combineObservationGroupRanges(groups) {
|
|
24437
|
-
const segments = groups.flatMap((group) => getRangeSegments(group.range));
|
|
24536
|
+
const segments = Array.from(new Set(groups.flatMap((group) => getRangeSegments(group.range))));
|
|
24438
24537
|
if (segments.length === 0) return "";
|
|
24439
|
-
const
|
|
24440
|
-
|
|
24441
|
-
|
|
24442
|
-
|
|
24443
|
-
|
|
24444
|
-
|
|
24538
|
+
const numericEndpoints = [];
|
|
24539
|
+
if (!segments.every((segment) => {
|
|
24540
|
+
const endpoints = getRangeEndpoints(segment);
|
|
24541
|
+
if (!endpoints || !/^\d+$/.test(endpoints.start) || !/^\d+$/.test(endpoints.end)) return false;
|
|
24542
|
+
const start = {
|
|
24543
|
+
label: endpoints.start,
|
|
24544
|
+
value: Number(endpoints.start)
|
|
24545
|
+
};
|
|
24546
|
+
const end = {
|
|
24547
|
+
label: endpoints.end,
|
|
24548
|
+
value: Number(endpoints.end)
|
|
24549
|
+
};
|
|
24550
|
+
if (!Number.isSafeInteger(start.value) || !Number.isSafeInteger(end.value)) return false;
|
|
24551
|
+
numericEndpoints.push(start.value <= end.value ? {
|
|
24552
|
+
start,
|
|
24553
|
+
end
|
|
24554
|
+
} : {
|
|
24555
|
+
start: end,
|
|
24556
|
+
end: start
|
|
24557
|
+
});
|
|
24558
|
+
return true;
|
|
24559
|
+
})) return spanRangeSegments(segments);
|
|
24560
|
+
const first = numericEndpoints.reduce((lowest, pair) => pair.start.value < lowest.start.value ? pair : lowest);
|
|
24561
|
+
const last = numericEndpoints.reduce((highest, pair) => pair.end.value > highest.end.value ? pair : highest);
|
|
24562
|
+
return `${first.start.label}:${last.end.label}`;
|
|
24445
24563
|
}
|
|
24446
24564
|
function renderObservationGroupsForReflection(observations) {
|
|
24447
|
-
|
|
24448
|
-
|
|
24449
|
-
|
|
24450
|
-
|
|
24451
|
-
|
|
24452
|
-
if (!group) return content.trim();
|
|
24453
|
-
return `## Group \`${group.id}\`\n_range: \`${group.range}\`_\n\n${group.content}`;
|
|
24565
|
+
if (parseObservationGroups(observations).length === 0) return null;
|
|
24566
|
+
return replaceObservationGroupTags(observations, (tag) => {
|
|
24567
|
+
const attributes = parseObservationGroupAttributes(tag.attributeString);
|
|
24568
|
+
if (!attributes.id || !attributes.range) return tag.content.trim();
|
|
24569
|
+
return `## Group \`${attributes.id}\`\n_range: \`${attributes.range}\`_\n\n${tag.content.trim()}`;
|
|
24454
24570
|
}).replace(/\n{3,}/g, "\n\n").trim();
|
|
24455
24571
|
}
|
|
24456
24572
|
function getCanonicalGroupId(sectionHeading, fallbackIndex) {
|
|
24457
24573
|
return sectionHeading.match(/`([^`]+)`/)?.[1]?.trim() || `derived-group-${fallbackIndex + 1}`;
|
|
24458
24574
|
}
|
|
24575
|
+
function getContentLines(content) {
|
|
24576
|
+
return content.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
24577
|
+
}
|
|
24459
24578
|
function deriveObservationGroupProvenance(content, groups) {
|
|
24460
24579
|
const sections = parseReflectionObservationGroupSections(content);
|
|
24461
24580
|
if (sections.length === 0 || groups.length === 0) return [];
|
|
24462
24581
|
return sections.map((section, index) => {
|
|
24463
|
-
const
|
|
24464
|
-
const
|
|
24465
|
-
|
|
24466
|
-
|
|
24582
|
+
const canonicalGroupId = getCanonicalGroupId(section.heading, index);
|
|
24583
|
+
const identifiedGroup = groups.find((group) => group.id === canonicalGroupId);
|
|
24584
|
+
const bodyLines = new Set(getContentLines(section.body));
|
|
24585
|
+
const matchingGroups = groups.filter((group) => getContentLines(group.content).some((line) => bodyLines.has(line)));
|
|
24467
24586
|
const fallbackGroup = groups[Math.min(index, groups.length - 1)];
|
|
24468
|
-
const
|
|
24587
|
+
const identifiedLines = new Set(getContentLines(identifiedGroup?.content ?? ""));
|
|
24588
|
+
const contributingGroups = identifiedGroup ? matchingGroups.filter((group) => group.id !== identifiedGroup.id && getContentLines(group.content).some((line) => bodyLines.has(line) && !identifiedLines.has(line))) : [];
|
|
24469
24589
|
return {
|
|
24470
|
-
id:
|
|
24471
|
-
range: combineObservationGroupRanges(
|
|
24590
|
+
id: canonicalGroupId,
|
|
24591
|
+
range: combineObservationGroupRanges(identifiedGroup ? groups.filter((group) => group === identifiedGroup || contributingGroups.includes(group)) : matchingGroups.length > 0 ? matchingGroups : fallbackGroup ? [fallbackGroup] : []),
|
|
24472
24592
|
kind: "reflection",
|
|
24473
24593
|
content: section.body
|
|
24474
24594
|
};
|
|
@@ -24896,6 +25016,23 @@ var ObservationStrategy = class ObservationStrategy {
|
|
|
24896
25016
|
}
|
|
24897
25017
|
};
|
|
24898
25018
|
//#endregion
|
|
25019
|
+
//#region src/processors/observational-memory/observation-strategies/thread-title.ts
|
|
25020
|
+
/**
|
|
25021
|
+
* Resolve the thread title an Observational Memory cycle should persist.
|
|
25022
|
+
*
|
|
25023
|
+
* Returns the trimmed candidate when it is a new, long-enough title, or
|
|
25024
|
+
* `undefined` when the current title must stay — including when the user
|
|
25025
|
+
* pinned it via `session.thread.rename()`, which sets the
|
|
25026
|
+
* `titlePinned` thread metadata flag.
|
|
25027
|
+
*/
|
|
25028
|
+
function resolveThreadTitleUpdate(thread, generatedTitle) {
|
|
25029
|
+
const candidate = generatedTitle?.trim();
|
|
25030
|
+
if (!candidate || candidate.length < 3) return void 0;
|
|
25031
|
+
if ((0, _mastra_core_memory.isThreadTitlePinned)(thread?.metadata)) return void 0;
|
|
25032
|
+
if (candidate === thread?.title?.trim()) return void 0;
|
|
25033
|
+
return candidate;
|
|
25034
|
+
}
|
|
25035
|
+
//#endregion
|
|
24899
25036
|
//#region src/processors/observational-memory/observation-strategies/sync.ts
|
|
24900
25037
|
var SyncObservationStrategy = class extends ObservationStrategy {
|
|
24901
25038
|
startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -25048,8 +25185,8 @@ var SyncObservationStrategy = class extends ObservationStrategy {
|
|
|
25048
25185
|
let threadUpdateMarker;
|
|
25049
25186
|
if (thread) {
|
|
25050
25187
|
const oldTitle = thread.title?.trim();
|
|
25051
|
-
const newTitle = processed.threadTitle
|
|
25052
|
-
const shouldUpdateThreadTitle =
|
|
25188
|
+
const newTitle = resolveThreadTitleUpdate(thread, processed.threadTitle);
|
|
25189
|
+
const shouldUpdateThreadTitle = newTitle !== void 0;
|
|
25053
25190
|
const previousOmMetadata = (0, _mastra_core_memory.getThreadOMMetadata)(thread.metadata);
|
|
25054
25191
|
const metadataUpdate = buildThreadMetadataFromExtractedValues(processed.extractors ?? this.observationConfig.extractors, processed.extractedValues);
|
|
25055
25192
|
const newMetadata = (0, _mastra_core_memory.setThreadOMMetadata)(thread.metadata, {
|
|
@@ -25248,13 +25385,14 @@ var AsyncBufferObservationStrategy = class extends ObservationStrategy {
|
|
|
25248
25385
|
abortSignal: this.opts.abortSignal
|
|
25249
25386
|
});
|
|
25250
25387
|
await this.indexObservationGroups(processed.observations, threadId, resourceId, processed.lastObservedAt);
|
|
25251
|
-
const
|
|
25252
|
-
const hasValidThreadTitle = !!
|
|
25388
|
+
const candidateTitle = processed.threadTitle?.trim();
|
|
25389
|
+
const hasValidThreadTitle = !!candidateTitle && candidateTitle.length >= 3;
|
|
25253
25390
|
if (hasValidThreadTitle || processed.extractedValues) {
|
|
25254
25391
|
const thread = await this.storage.getThreadById({ threadId });
|
|
25255
25392
|
if (thread) {
|
|
25256
25393
|
const oldTitle = thread.title?.trim();
|
|
25257
|
-
const
|
|
25394
|
+
const newTitle = resolveThreadTitleUpdate(thread, candidateTitle);
|
|
25395
|
+
const shouldUpdateThreadTitle = newTitle !== void 0;
|
|
25258
25396
|
const previousOmMetadata = (0, _mastra_core_memory.getThreadOMMetadata)(thread.metadata);
|
|
25259
25397
|
const metadataUpdate = buildThreadMetadataFromExtractedValues(processed.extractors ?? this.observationConfig.extractors, processed.extractedValues);
|
|
25260
25398
|
const newMetadata = (0, _mastra_core_memory.setThreadOMMetadata)(thread.metadata, {
|
|
@@ -25611,8 +25749,8 @@ var ResourceScopedObservationStrategy = class extends ObservationStrategy {
|
|
|
25611
25749
|
const thread = await this.storage.getThreadById({ threadId: update.threadId });
|
|
25612
25750
|
if (thread) {
|
|
25613
25751
|
const oldTitle = thread.title?.trim();
|
|
25614
|
-
const newTitle = update.threadTitle
|
|
25615
|
-
const shouldUpdateThreadTitle =
|
|
25752
|
+
const newTitle = resolveThreadTitleUpdate(thread, update.threadTitle);
|
|
25753
|
+
const shouldUpdateThreadTitle = newTitle !== void 0;
|
|
25616
25754
|
const previousOmMetadata = (0, _mastra_core_memory.getThreadOMMetadata)(thread.metadata);
|
|
25617
25755
|
const metadataUpdate = buildThreadMetadataFromExtractedValues(update.extractors ?? this.observationConfig.extractors, update.extracted);
|
|
25618
25756
|
const newMetadata = (0, _mastra_core_memory.setThreadOMMetadata)(thread.metadata, {
|
|
@@ -28045,11 +28183,19 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
28045
28183
|
const messageTokens = config.observation?.messageTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.messageTokens;
|
|
28046
28184
|
const observationTokens = config.reflection?.observationTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.observationTokens;
|
|
28047
28185
|
const isSharedBudget = config.shareTokenBudget ?? false;
|
|
28048
|
-
const
|
|
28186
|
+
const supportsDefaultTemperature = (model) => {
|
|
28187
|
+
if (model instanceof ModelByInputTokens || typeof model === "function") return false;
|
|
28188
|
+
if (typeof model === "string") return (0, _mastra_core_llm.modelSupportsTemperature)(model) === true;
|
|
28189
|
+
if (model && typeof model === "object" && "provider" in model && "modelId" in model && typeof model.provider === "string" && typeof model.modelId === "string") return (0, _mastra_core_llm.modelSupportsTemperature)(`${model.provider.split(".")[0]}/${model.modelId}`) === true;
|
|
28190
|
+
return false;
|
|
28191
|
+
};
|
|
28192
|
+
const usesDefaultOutputTokenBudget = (model) => model === void 0 || model === "default" || model instanceof ModelByInputTokens;
|
|
28049
28193
|
const observationSelectedModel = topLevelModel ?? observationConfigModel ?? reflectionConfigModel;
|
|
28050
28194
|
const reflectionSelectedModel = topLevelModel ?? reflectionConfigModel ?? observationConfigModel;
|
|
28051
|
-
const
|
|
28052
|
-
const
|
|
28195
|
+
const observationTemperature = config.observation?.modelSettings?.temperature ?? (supportsDefaultTemperature(observationModel) ? OBSERVATIONAL_MEMORY_DEFAULTS.observation.modelSettings.temperature : void 0);
|
|
28196
|
+
const observationDefaultMaxOutputTokens = config.observation?.modelSettings?.maxOutputTokens ?? (usesDefaultOutputTokenBudget(observationSelectedModel) ? OBSERVATIONAL_MEMORY_DEFAULTS.observation.modelSettings.maxOutputTokens : void 0);
|
|
28197
|
+
const reflectionTemperature = config.reflection?.modelSettings?.temperature ?? (supportsDefaultTemperature(reflectionModel) ? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.modelSettings.temperature : void 0);
|
|
28198
|
+
const reflectionDefaultMaxOutputTokens = config.reflection?.modelSettings?.maxOutputTokens ?? (usesDefaultOutputTokenBudget(reflectionSelectedModel) ? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.modelSettings.maxOutputTokens : void 0);
|
|
28053
28199
|
const totalBudget = messageTokens + observationTokens;
|
|
28054
28200
|
const userExplicitlyConfiguredAsync = config.observation?.bufferTokens !== void 0 || config.observation?.bufferActivation !== void 0 || config.reflection?.bufferActivation !== void 0;
|
|
28055
28201
|
const asyncBufferingDisabled = config.observation?.bufferTokens === false || config.scope === "resource" && !userExplicitlyConfiguredAsync;
|
|
@@ -28065,7 +28211,7 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
28065
28211
|
} : messageTokens,
|
|
28066
28212
|
shareTokenBudget: isSharedBudget,
|
|
28067
28213
|
modelSettings: {
|
|
28068
|
-
temperature:
|
|
28214
|
+
...observationTemperature !== void 0 ? { temperature: observationTemperature } : {},
|
|
28069
28215
|
...observationDefaultMaxOutputTokens !== void 0 ? { maxOutputTokens: observationDefaultMaxOutputTokens } : {}
|
|
28070
28216
|
},
|
|
28071
28217
|
providerOptions: config.observation?.providerOptions ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.providerOptions,
|
|
@@ -28091,7 +28237,7 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
28091
28237
|
observationTokens,
|
|
28092
28238
|
shareTokenBudget: isSharedBudget,
|
|
28093
28239
|
modelSettings: {
|
|
28094
|
-
temperature:
|
|
28240
|
+
...reflectionTemperature !== void 0 ? { temperature: reflectionTemperature } : {},
|
|
28095
28241
|
...reflectionDefaultMaxOutputTokens !== void 0 ? { maxOutputTokens: reflectionDefaultMaxOutputTokens } : {}
|
|
28096
28242
|
},
|
|
28097
28243
|
providerOptions: config.reflection?.providerOptions ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.providerOptions,
|
|
@@ -29815,9 +29961,8 @@ ${formattedMessages}
|
|
|
29815
29961
|
currentTask: lastActivated.currentTask,
|
|
29816
29962
|
threadTitle: chunkThreadTitle
|
|
29817
29963
|
});
|
|
29818
|
-
const
|
|
29819
|
-
const
|
|
29820
|
-
const shouldUpdateThreadTitle = !!newTitle && newTitle.length >= 3 && newTitle !== oldTitle;
|
|
29964
|
+
const newTitle = resolveThreadTitleUpdate(thread, chunkThreadTitle);
|
|
29965
|
+
const shouldUpdateThreadTitle = newTitle !== void 0;
|
|
29821
29966
|
await this.storage.patchThread({
|
|
29822
29967
|
id: threadId,
|
|
29823
29968
|
...shouldUpdateThreadTitle ? { title: newTitle } : {},
|
|
@@ -31209,6 +31354,13 @@ var Memory = class Memory extends _mastra_core_memory.MastraMemory {
|
|
|
31209
31354
|
});
|
|
31210
31355
|
return savedThread;
|
|
31211
31356
|
}
|
|
31357
|
+
/**
|
|
31358
|
+
* Update a thread's title or metadata.
|
|
31359
|
+
*
|
|
31360
|
+
* Unlike `session.thread.rename()`, this does not pin the title, so
|
|
31361
|
+
* Observational Memory may still replace it with an extracted title. To
|
|
31362
|
+
* protect a manual rename, set `metadata.titlePinned` to `true`.
|
|
31363
|
+
*/
|
|
31212
31364
|
async updateThread({ id, title, metadata, memoryConfig }) {
|
|
31213
31365
|
const updatedThread = await (await this.getMemoryStore()).patchThread({
|
|
31214
31366
|
id,
|
|
@@ -33245,4 +33397,4 @@ Object.defineProperty(exports, "wrapInObservationGroup", {
|
|
|
33245
33397
|
}
|
|
33246
33398
|
});
|
|
33247
33399
|
|
|
33248
|
-
//# sourceMappingURL=src-
|
|
33400
|
+
//# sourceMappingURL=src-C4niho1P.cjs.map
|