@mastra/memory 1.31.0-alpha.1 → 1.31.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/docs/references/docs-memory-observational-memory.md +33 -0
- package/dist/docs/references/integrations-channels-github.md +6 -2
- 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.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/sync.d.ts.map +1 -1
- package/dist/processors/observational-memory/observation-turn/turn.d.ts +2 -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/types.d.ts +6 -6
- package/dist/{src-Ju0u9OWc.js → src-CSVmHSng.js} +256 -52
- package/dist/src-CSVmHSng.js.map +1 -0
- package/dist/{src-BCvV2aGL.cjs → src-QqTmOY5X.cjs} +271 -67
- package/dist/src-QqTmOY5X.cjs.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-BCvV2aGL.cjs.map +0 -1
- package/dist/src-Ju0u9OWc.js.map +0 -1
|
@@ -18,8 +18,7 @@ import { appendFileSync, mkdirSync, writeFileSync } from "fs";
|
|
|
18
18
|
import { join } from "path";
|
|
19
19
|
import { createTool } from "@mastra/core/tools";
|
|
20
20
|
import { MASTRA_THREAD_ID_KEY, RequestContext } from "@mastra/core/request-context";
|
|
21
|
-
import { modelSupportsAttachments, resolveModelConfig } from "@mastra/core/llm";
|
|
22
|
-
import { estimateTokenCount } from "tokenx";
|
|
21
|
+
import { modelSupportsAttachments, modelSupportsTemperature, resolveModelConfig } from "@mastra/core/llm";
|
|
23
22
|
import { AsyncLocalStorage } from "async_hooks";
|
|
24
23
|
import probeImageSizeSync from "probe-image-size/sync.js";
|
|
25
24
|
import { isStandardSchemaWithJSON as isStandardSchemaWithJSON$1, toStandardSchema as toStandardSchema$1 } from "@mastra/core/schema";
|
|
@@ -18304,6 +18303,62 @@ function safeSlice(str, end) {
|
|
|
18304
18303
|
return str.slice(0, safeEnd);
|
|
18305
18304
|
}
|
|
18306
18305
|
//#endregion
|
|
18306
|
+
//#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/tokenx/1.3.0/09093cdaeebfe25c39ba9052d6277b45fc99abf5e14e859f60f338f5c5160afd/node_modules/tokenx/dist/index.mjs
|
|
18307
|
+
const PATTERNS = {
|
|
18308
|
+
whitespace: /^\s+$/,
|
|
18309
|
+
cjk: /[\u4E00-\u9FFF\u3400-\u4DBF\u3000-\u303F\uFF00-\uFFEF\u30A0-\u30FF\u2E80-\u2EFF\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uAC00-\uD7AF\u1100-\u11FF\u3130-\u318F\uA960-\uA97F\uD7B0-\uD7FF]/,
|
|
18310
|
+
numeric: /^\d+(?:[.,]\d+)*$/,
|
|
18311
|
+
punctuation: /[.,!?;(){}[\]<>:/\\|@#$%^&*+=`~_-]/,
|
|
18312
|
+
alphanumeric: /^[a-zA-Z0-9\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]+$/
|
|
18313
|
+
};
|
|
18314
|
+
const TOKEN_SPLIT_PATTERN = /* @__PURE__ */ new RegExp(`(\\s+|${PATTERNS.punctuation.source}+)`);
|
|
18315
|
+
const DEFAULT_CHARS_PER_TOKEN = 6;
|
|
18316
|
+
const SHORT_TOKEN_THRESHOLD = 3;
|
|
18317
|
+
const DEFAULT_LANGUAGE_CONFIGS = [
|
|
18318
|
+
{
|
|
18319
|
+
pattern: /[äöüßẞ]/i,
|
|
18320
|
+
averageCharsPerToken: 3
|
|
18321
|
+
},
|
|
18322
|
+
{
|
|
18323
|
+
pattern: /[éèêëàâîïôûùüÿçœæáíóúñ]/i,
|
|
18324
|
+
averageCharsPerToken: 3
|
|
18325
|
+
},
|
|
18326
|
+
{
|
|
18327
|
+
pattern: /[ąćęłńóśźżěščřžýůúďťň]/i,
|
|
18328
|
+
averageCharsPerToken: 3.5
|
|
18329
|
+
}
|
|
18330
|
+
];
|
|
18331
|
+
/**
|
|
18332
|
+
* Estimates the number of tokens in a text string using heuristic rules.
|
|
18333
|
+
*/
|
|
18334
|
+
function estimateTokenCount(text, options = {}) {
|
|
18335
|
+
if (!text) return 0;
|
|
18336
|
+
const { defaultCharsPerToken = DEFAULT_CHARS_PER_TOKEN, languageConfigs = DEFAULT_LANGUAGE_CONFIGS } = options;
|
|
18337
|
+
const segments = text.split(TOKEN_SPLIT_PATTERN).filter(Boolean);
|
|
18338
|
+
let tokenCount = 0;
|
|
18339
|
+
for (const segment of segments) tokenCount += estimateSegmentTokens(segment, languageConfigs, defaultCharsPerToken);
|
|
18340
|
+
return tokenCount;
|
|
18341
|
+
}
|
|
18342
|
+
function estimateSegmentTokens(segment, languageConfigs, defaultCharsPerToken) {
|
|
18343
|
+
if (PATTERNS.whitespace.test(segment)) return 0;
|
|
18344
|
+
if (PATTERNS.cjk.test(segment)) return getCharacterCount(segment);
|
|
18345
|
+
if (PATTERNS.numeric.test(segment)) return 1;
|
|
18346
|
+
if (segment.length <= SHORT_TOKEN_THRESHOLD) return 1;
|
|
18347
|
+
if (PATTERNS.punctuation.test(segment)) return segment.length > 1 ? Math.ceil(segment.length / 2) : 1;
|
|
18348
|
+
if (PATTERNS.alphanumeric.test(segment)) {
|
|
18349
|
+
const charsPerToken$1 = getLanguageSpecificCharsPerToken(segment, languageConfigs) ?? defaultCharsPerToken;
|
|
18350
|
+
return Math.ceil(segment.length / charsPerToken$1);
|
|
18351
|
+
}
|
|
18352
|
+
const charsPerToken = getLanguageSpecificCharsPerToken(segment, languageConfigs) ?? defaultCharsPerToken;
|
|
18353
|
+
return Math.ceil(segment.length / charsPerToken);
|
|
18354
|
+
}
|
|
18355
|
+
function getLanguageSpecificCharsPerToken(segment, languageConfigs) {
|
|
18356
|
+
for (const config of languageConfigs) if (config.pattern.test(segment)) return config.averageCharsPerToken;
|
|
18357
|
+
}
|
|
18358
|
+
function getCharacterCount(text) {
|
|
18359
|
+
return Array.from(text).length;
|
|
18360
|
+
}
|
|
18361
|
+
//#endregion
|
|
18307
18362
|
//#region src/processors/observational-memory/tool-argument-helpers.ts
|
|
18308
18363
|
const DEFAULT_OBSERVER_TOOL_ARGUMENT_MAX_TOKENS = 2e3;
|
|
18309
18364
|
const OBSERVER_TOOL_ARGUMENT_INLINE_STRING_MAX_CHARS = 160;
|
|
@@ -22778,13 +22833,13 @@ function renderFormattedParts(parts, timestamps, options) {
|
|
|
22778
22833
|
tokenOffset: expandedTokens - options.maxTokens
|
|
22779
22834
|
};
|
|
22780
22835
|
}
|
|
22781
|
-
async function recallPart({ memory, threadId, resourceId, cursor, partIndex, charOffset, threadScope, maxTokens = DEFAULT_MAX_RESULT_TOKENS }) {
|
|
22836
|
+
async function recallPart({ memory, threadId, resourceId, cursor, partIndex, charOffset, threadScope, retrievalScope = "thread", maxTokens = DEFAULT_MAX_RESULT_TOKENS }) {
|
|
22782
22837
|
if (!memory || typeof memory.getMemoryStore !== "function") throw new Error("Memory instance is required for recall");
|
|
22783
22838
|
if (!threadId) throw new Error("Thread ID is required for recall");
|
|
22784
22839
|
const resolved = await resolveCursorMessage(memory, cursor, {
|
|
22785
22840
|
resourceId,
|
|
22786
22841
|
threadScope,
|
|
22787
|
-
enforceThreadScope:
|
|
22842
|
+
enforceThreadScope: retrievalScope !== "resource"
|
|
22788
22843
|
});
|
|
22789
22844
|
if ("hint" in resolved) throw new Error(resolved.hint);
|
|
22790
22845
|
const allParts = formatMessageParts(resolved, "high");
|
|
@@ -22795,7 +22850,7 @@ async function recallPart({ memory, threadId, resourceId, cursor, partIndex, cha
|
|
|
22795
22850
|
if (partIndex > Math.max(...allParts.map((p) => p.partIndex))) {
|
|
22796
22851
|
const nextMessage = await getNextVisibleMessage({
|
|
22797
22852
|
memory,
|
|
22798
|
-
threadId,
|
|
22853
|
+
threadId: resolved.threadId ?? threadId,
|
|
22799
22854
|
resourceId,
|
|
22800
22855
|
after: resolved.createdAt
|
|
22801
22856
|
});
|
|
@@ -22834,7 +22889,7 @@ async function recallPart({ memory, threadId, resourceId, cursor, partIndex, cha
|
|
|
22834
22889
|
note
|
|
22835
22890
|
};
|
|
22836
22891
|
}
|
|
22837
|
-
async function recallMessages({ memory, threadId, resourceId, cursor, page = 1, limit = 20, detail = "low", partType, toolName, threadScope, maxTokens = DEFAULT_MAX_RESULT_TOKENS }) {
|
|
22892
|
+
async function recallMessages({ memory, threadId, resourceId, cursor, page = 1, limit = 20, detail = "low", partType, toolName, threadScope, retrievalScope = "thread", maxTokens = DEFAULT_MAX_RESULT_TOKENS }) {
|
|
22838
22893
|
if (!memory) throw new Error("Memory instance is required for recall");
|
|
22839
22894
|
if (!threadId) throw new Error("Thread ID is required for recall");
|
|
22840
22895
|
if (typeof memory.getMemoryStore !== "function") throw new Error("recall requires a Memory instance with storage access");
|
|
@@ -22845,7 +22900,7 @@ async function recallMessages({ memory, threadId, resourceId, cursor, page = 1,
|
|
|
22845
22900
|
const resolved = await resolveCursorMessage(memory, cursor, {
|
|
22846
22901
|
resourceId,
|
|
22847
22902
|
threadScope,
|
|
22848
|
-
enforceThreadScope:
|
|
22903
|
+
enforceThreadScope: retrievalScope === "thread"
|
|
22849
22904
|
});
|
|
22850
22905
|
if ("hint" in resolved) return {
|
|
22851
22906
|
messages: resolved.hint,
|
|
@@ -22862,7 +22917,7 @@ async function recallMessages({ memory, threadId, resourceId, cursor, page = 1,
|
|
|
22862
22917
|
const anchor = resolved;
|
|
22863
22918
|
const crossThreadId = anchor.threadId && anchor.threadId !== threadId ? anchor.threadId : void 0;
|
|
22864
22919
|
if (crossThreadId && threadScope) return {
|
|
22865
|
-
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
|
|
22920
|
+
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.`,
|
|
22866
22921
|
count: 0,
|
|
22867
22922
|
cursor,
|
|
22868
22923
|
page: normalizedPage,
|
|
@@ -23021,7 +23076,8 @@ async function recallThreadFromStart({ memory, threadId, resourceId, page = 1, l
|
|
|
23021
23076
|
};
|
|
23022
23077
|
}
|
|
23023
23078
|
const recallTool = (_memoryConfig, options) => {
|
|
23024
|
-
const
|
|
23079
|
+
const retrievalScope = options?.retrievalScope ?? "thread";
|
|
23080
|
+
const isResourceScope = retrievalScope === "resource";
|
|
23025
23081
|
const searchEnabled = options?.searchEnabled ?? true;
|
|
23026
23082
|
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.`;
|
|
23027
23083
|
const modeEnum = searchEnabled ? [
|
|
@@ -23232,23 +23288,25 @@ const recallTool = (_memoryConfig, options) => {
|
|
|
23232
23288
|
if (partIndex !== void 0 && partIndex !== null) return recallPart({
|
|
23233
23289
|
memory,
|
|
23234
23290
|
threadId: targetThreadId,
|
|
23235
|
-
resourceId
|
|
23291
|
+
resourceId,
|
|
23236
23292
|
cursor,
|
|
23237
23293
|
partIndex,
|
|
23238
23294
|
charOffset,
|
|
23239
|
-
threadScope
|
|
23295
|
+
threadScope,
|
|
23296
|
+
retrievalScope
|
|
23240
23297
|
});
|
|
23241
23298
|
return recallMessages({
|
|
23242
23299
|
memory,
|
|
23243
23300
|
threadId: targetThreadId,
|
|
23244
|
-
resourceId
|
|
23301
|
+
resourceId,
|
|
23245
23302
|
cursor,
|
|
23246
23303
|
page,
|
|
23247
23304
|
limit,
|
|
23248
23305
|
detail: detail ?? "low",
|
|
23249
23306
|
partType,
|
|
23250
23307
|
toolName,
|
|
23251
|
-
threadScope
|
|
23308
|
+
threadScope,
|
|
23309
|
+
retrievalScope
|
|
23252
23310
|
});
|
|
23253
23311
|
}
|
|
23254
23312
|
});
|
|
@@ -24354,7 +24412,8 @@ function stripThreadTags(observations) {
|
|
|
24354
24412
|
}
|
|
24355
24413
|
//#endregion
|
|
24356
24414
|
//#region src/processors/observational-memory/observation-groups.ts
|
|
24357
|
-
const
|
|
24415
|
+
const OBSERVATION_GROUP_OPEN = "<observation-group";
|
|
24416
|
+
const OBSERVATION_GROUP_CLOSE = "</observation-group>";
|
|
24358
24417
|
const ATTRIBUTE_PATTERN = /([\w][\w-]*)="([^"]*)"/g;
|
|
24359
24418
|
const REFLECTION_GROUP_SPLIT_PATTERN = /^##\s+Group\s+/m;
|
|
24360
24419
|
function parseObservationGroupAttributes(attributeString) {
|
|
@@ -24365,6 +24424,81 @@ function parseObservationGroupAttributes(attributeString) {
|
|
|
24365
24424
|
}
|
|
24366
24425
|
return attributes;
|
|
24367
24426
|
}
|
|
24427
|
+
function isLineStart(observations, index) {
|
|
24428
|
+
return index === 0 || observations[index - 1] === "\n";
|
|
24429
|
+
}
|
|
24430
|
+
function scanObservationGroupTags(observations) {
|
|
24431
|
+
const tags = [];
|
|
24432
|
+
const incompleteOpenings = [];
|
|
24433
|
+
let cursor = 0;
|
|
24434
|
+
let closeFloor = 0;
|
|
24435
|
+
while (cursor < observations.length) {
|
|
24436
|
+
const start = observations.indexOf(OBSERVATION_GROUP_OPEN, cursor);
|
|
24437
|
+
if (start === -1) break;
|
|
24438
|
+
const attributesStart = start + 18;
|
|
24439
|
+
if (!/\s/.test(observations[attributesStart] ?? "")) {
|
|
24440
|
+
cursor = attributesStart;
|
|
24441
|
+
continue;
|
|
24442
|
+
}
|
|
24443
|
+
const openEnd = observations.indexOf(">", attributesStart);
|
|
24444
|
+
if (openEnd === -1) break;
|
|
24445
|
+
const closeStart = observations.indexOf(OBSERVATION_GROUP_CLOSE, Math.max(openEnd + 1, closeFloor));
|
|
24446
|
+
if (closeStart === -1) {
|
|
24447
|
+
if (isLineStart(observations, start)) incompleteOpenings.push({
|
|
24448
|
+
start,
|
|
24449
|
+
end: openEnd + 1
|
|
24450
|
+
});
|
|
24451
|
+
closeFloor = observations.length;
|
|
24452
|
+
cursor = openEnd + 1;
|
|
24453
|
+
continue;
|
|
24454
|
+
}
|
|
24455
|
+
const nestedStart = observations.indexOf(OBSERVATION_GROUP_OPEN, openEnd + 1);
|
|
24456
|
+
if (nestedStart !== -1 && nestedStart < closeStart && isLineStart(observations, nestedStart)) {
|
|
24457
|
+
incompleteOpenings.push({
|
|
24458
|
+
start,
|
|
24459
|
+
end: openEnd + 1
|
|
24460
|
+
});
|
|
24461
|
+
closeFloor = closeStart;
|
|
24462
|
+
cursor = nestedStart;
|
|
24463
|
+
continue;
|
|
24464
|
+
}
|
|
24465
|
+
tags.push({
|
|
24466
|
+
start,
|
|
24467
|
+
end: closeStart + 20,
|
|
24468
|
+
attributeString: observations.slice(attributesStart, openEnd),
|
|
24469
|
+
content: observations.slice(openEnd + 1, closeStart)
|
|
24470
|
+
});
|
|
24471
|
+
closeFloor = closeStart;
|
|
24472
|
+
cursor = closeStart + 20;
|
|
24473
|
+
}
|
|
24474
|
+
return {
|
|
24475
|
+
tags,
|
|
24476
|
+
incompleteOpenings
|
|
24477
|
+
};
|
|
24478
|
+
}
|
|
24479
|
+
function replaceObservationGroupTags(observations, replace) {
|
|
24480
|
+
const { tags, incompleteOpenings } = scanObservationGroupTags(observations);
|
|
24481
|
+
const parts = [];
|
|
24482
|
+
let cursor = 0;
|
|
24483
|
+
let openingIndex = 0;
|
|
24484
|
+
const skipIncompleteOpeningsBefore = (limit) => {
|
|
24485
|
+
while (openingIndex < incompleteOpenings.length && incompleteOpenings[openingIndex].start < limit) {
|
|
24486
|
+
const opening = incompleteOpenings[openingIndex];
|
|
24487
|
+
openingIndex++;
|
|
24488
|
+
if (opening.start < cursor) continue;
|
|
24489
|
+
parts.push(observations.slice(cursor, opening.start));
|
|
24490
|
+
cursor = opening.end;
|
|
24491
|
+
}
|
|
24492
|
+
};
|
|
24493
|
+
for (const tag of tags) {
|
|
24494
|
+
skipIncompleteOpeningsBefore(tag.start);
|
|
24495
|
+
parts.push(observations.slice(cursor, tag.start), replace(tag));
|
|
24496
|
+
cursor = tag.end;
|
|
24497
|
+
}
|
|
24498
|
+
skipIncompleteOpeningsBefore(Number.POSITIVE_INFINITY);
|
|
24499
|
+
parts.push(observations.slice(cursor));
|
|
24500
|
+
return parts.join("");
|
|
24501
|
+
}
|
|
24368
24502
|
function parseReflectionObservationGroupSections(content) {
|
|
24369
24503
|
const normalizedContent = content.trim();
|
|
24370
24504
|
if (!normalizedContent || !REFLECTION_GROUP_SPLIT_PATTERN.test(normalizedContent)) return [];
|
|
@@ -24389,9 +24523,8 @@ function wrapInObservationGroup(observations, range, id = generateAnchorId(), _s
|
|
|
24389
24523
|
function parseObservationGroups(observations) {
|
|
24390
24524
|
if (!observations) return [];
|
|
24391
24525
|
const groups = [];
|
|
24392
|
-
|
|
24393
|
-
|
|
24394
|
-
const attributes = parseObservationGroupAttributes(match[1] ?? "");
|
|
24526
|
+
for (const tag of scanObservationGroupTags(observations).tags) {
|
|
24527
|
+
const attributes = parseObservationGroupAttributes(tag.attributeString);
|
|
24395
24528
|
const id = attributes.id;
|
|
24396
24529
|
const range = attributes.range;
|
|
24397
24530
|
if (!id || !range) continue;
|
|
@@ -24399,54 +24532,96 @@ function parseObservationGroups(observations) {
|
|
|
24399
24532
|
id,
|
|
24400
24533
|
range,
|
|
24401
24534
|
kind: attributes.kind,
|
|
24402
|
-
content:
|
|
24535
|
+
content: tag.content.trim()
|
|
24403
24536
|
});
|
|
24404
24537
|
}
|
|
24405
24538
|
return groups;
|
|
24406
24539
|
}
|
|
24407
24540
|
function stripObservationGroups(observations) {
|
|
24408
24541
|
if (!observations) return observations;
|
|
24409
|
-
return observations
|
|
24542
|
+
return replaceObservationGroupTags(observations, (tag) => tag.content.trim()).replace(/\n{3,}/g, "\n\n").trim();
|
|
24410
24543
|
}
|
|
24411
24544
|
function getRangeSegments(range) {
|
|
24412
24545
|
return range.split(",").map((segment) => segment.trim()).filter(Boolean);
|
|
24413
24546
|
}
|
|
24547
|
+
function getRangeEndpoints(segment) {
|
|
24548
|
+
const parts = segment.split(":").map((part) => part.trim());
|
|
24549
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) return null;
|
|
24550
|
+
return {
|
|
24551
|
+
start: parts[0],
|
|
24552
|
+
end: parts[1]
|
|
24553
|
+
};
|
|
24554
|
+
}
|
|
24555
|
+
/**
|
|
24556
|
+
* `buildMessageRange` produces opaque UUID endpoints, so those segments cannot be ordered by value.
|
|
24557
|
+
* Spanning from the first start to the last end keeps reflected metadata bounded — the full segment
|
|
24558
|
+
* list is deliberately not preserved (#14791). Segments that are not `start:end` pairs are left as
|
|
24559
|
+
* they are rather than being joined into a fabricated span.
|
|
24560
|
+
*/
|
|
24561
|
+
function spanRangeSegments(segments) {
|
|
24562
|
+
const endpoints = segments.map(getRangeEndpoints);
|
|
24563
|
+
if (endpoints.some((endpoint) => endpoint === null)) return segments.join(",");
|
|
24564
|
+
const first = endpoints[0];
|
|
24565
|
+
const last = endpoints.at(-1);
|
|
24566
|
+
return `${first.start}:${last.end}`;
|
|
24567
|
+
}
|
|
24414
24568
|
function combineObservationGroupRanges(groups) {
|
|
24415
|
-
const segments = groups.flatMap((group) => getRangeSegments(group.range));
|
|
24569
|
+
const segments = Array.from(new Set(groups.flatMap((group) => getRangeSegments(group.range))));
|
|
24416
24570
|
if (segments.length === 0) return "";
|
|
24417
|
-
const
|
|
24418
|
-
|
|
24419
|
-
|
|
24420
|
-
|
|
24421
|
-
|
|
24422
|
-
|
|
24571
|
+
const numericEndpoints = [];
|
|
24572
|
+
if (!segments.every((segment) => {
|
|
24573
|
+
const endpoints = getRangeEndpoints(segment);
|
|
24574
|
+
if (!endpoints || !/^\d+$/.test(endpoints.start) || !/^\d+$/.test(endpoints.end)) return false;
|
|
24575
|
+
const start = {
|
|
24576
|
+
label: endpoints.start,
|
|
24577
|
+
value: Number(endpoints.start)
|
|
24578
|
+
};
|
|
24579
|
+
const end = {
|
|
24580
|
+
label: endpoints.end,
|
|
24581
|
+
value: Number(endpoints.end)
|
|
24582
|
+
};
|
|
24583
|
+
if (!Number.isSafeInteger(start.value) || !Number.isSafeInteger(end.value)) return false;
|
|
24584
|
+
numericEndpoints.push(start.value <= end.value ? {
|
|
24585
|
+
start,
|
|
24586
|
+
end
|
|
24587
|
+
} : {
|
|
24588
|
+
start: end,
|
|
24589
|
+
end: start
|
|
24590
|
+
});
|
|
24591
|
+
return true;
|
|
24592
|
+
})) return spanRangeSegments(segments);
|
|
24593
|
+
const first = numericEndpoints.reduce((lowest, pair) => pair.start.value < lowest.start.value ? pair : lowest);
|
|
24594
|
+
const last = numericEndpoints.reduce((highest, pair) => pair.end.value > highest.end.value ? pair : highest);
|
|
24595
|
+
return `${first.start.label}:${last.end.label}`;
|
|
24423
24596
|
}
|
|
24424
24597
|
function renderObservationGroupsForReflection(observations) {
|
|
24425
|
-
|
|
24426
|
-
|
|
24427
|
-
|
|
24428
|
-
|
|
24429
|
-
|
|
24430
|
-
if (!group) return content.trim();
|
|
24431
|
-
return `## Group \`${group.id}\`\n_range: \`${group.range}\`_\n\n${group.content}`;
|
|
24598
|
+
if (parseObservationGroups(observations).length === 0) return null;
|
|
24599
|
+
return replaceObservationGroupTags(observations, (tag) => {
|
|
24600
|
+
const attributes = parseObservationGroupAttributes(tag.attributeString);
|
|
24601
|
+
if (!attributes.id || !attributes.range) return tag.content.trim();
|
|
24602
|
+
return `## Group \`${attributes.id}\`\n_range: \`${attributes.range}\`_\n\n${tag.content.trim()}`;
|
|
24432
24603
|
}).replace(/\n{3,}/g, "\n\n").trim();
|
|
24433
24604
|
}
|
|
24434
24605
|
function getCanonicalGroupId(sectionHeading, fallbackIndex) {
|
|
24435
24606
|
return sectionHeading.match(/`([^`]+)`/)?.[1]?.trim() || `derived-group-${fallbackIndex + 1}`;
|
|
24436
24607
|
}
|
|
24608
|
+
function getContentLines(content) {
|
|
24609
|
+
return content.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
24610
|
+
}
|
|
24437
24611
|
function deriveObservationGroupProvenance(content, groups) {
|
|
24438
24612
|
const sections = parseReflectionObservationGroupSections(content);
|
|
24439
24613
|
if (sections.length === 0 || groups.length === 0) return [];
|
|
24440
24614
|
return sections.map((section, index) => {
|
|
24441
|
-
const
|
|
24442
|
-
const
|
|
24443
|
-
|
|
24444
|
-
|
|
24615
|
+
const canonicalGroupId = getCanonicalGroupId(section.heading, index);
|
|
24616
|
+
const identifiedGroup = groups.find((group) => group.id === canonicalGroupId);
|
|
24617
|
+
const bodyLines = new Set(getContentLines(section.body));
|
|
24618
|
+
const matchingGroups = groups.filter((group) => getContentLines(group.content).some((line) => bodyLines.has(line)));
|
|
24445
24619
|
const fallbackGroup = groups[Math.min(index, groups.length - 1)];
|
|
24446
|
-
const
|
|
24620
|
+
const identifiedLines = new Set(getContentLines(identifiedGroup?.content ?? ""));
|
|
24621
|
+
const contributingGroups = identifiedGroup ? matchingGroups.filter((group) => group.id !== identifiedGroup.id && getContentLines(group.content).some((line) => bodyLines.has(line) && !identifiedLines.has(line))) : [];
|
|
24447
24622
|
return {
|
|
24448
|
-
id:
|
|
24449
|
-
range: combineObservationGroupRanges(
|
|
24623
|
+
id: canonicalGroupId,
|
|
24624
|
+
range: combineObservationGroupRanges(identifiedGroup ? groups.filter((group) => group === identifiedGroup || contributingGroups.includes(group)) : matchingGroups.length > 0 ? matchingGroups : fallbackGroup ? [fallbackGroup] : []),
|
|
24450
24625
|
kind: "reflection",
|
|
24451
24626
|
content: section.body
|
|
24452
24627
|
};
|
|
@@ -25040,6 +25215,10 @@ var SyncObservationStrategy = class extends ObservationStrategy {
|
|
|
25040
25215
|
async persist(processed) {
|
|
25041
25216
|
const { record, threadId, resourceId, messages } = this.opts;
|
|
25042
25217
|
const thread = await this.storage.getThreadById({ threadId });
|
|
25218
|
+
if (!await this.storage.getObservationalMemory(record.threadId, record.resourceId)) {
|
|
25219
|
+
omDebug(`[OM:sync-obs] skipping persist for thread ${threadId}: observational memory record is gone`);
|
|
25220
|
+
return;
|
|
25221
|
+
}
|
|
25043
25222
|
let threadUpdateMarker;
|
|
25044
25223
|
if (thread) {
|
|
25045
25224
|
const oldTitle = thread.title?.trim();
|
|
@@ -25221,6 +25400,10 @@ var AsyncBufferObservationStrategy = class extends ObservationStrategy {
|
|
|
25221
25400
|
async persist(processed) {
|
|
25222
25401
|
if (!processed.observations) return;
|
|
25223
25402
|
const { record, threadId, resourceId, messages } = this.opts;
|
|
25403
|
+
if (!await this.storage.getObservationalMemory(record.threadId, record.resourceId)) {
|
|
25404
|
+
omDebug(`[OM:asyncBuffer] skipping persist for thread ${threadId}: observational memory record is gone`);
|
|
25405
|
+
return;
|
|
25406
|
+
}
|
|
25224
25407
|
const messageTokens = await this.tokenCounter.countMessagesAsync(messages);
|
|
25225
25408
|
await withRetry(() => this.storage.updateBufferedObservations({
|
|
25226
25409
|
id: record.id,
|
|
@@ -26214,6 +26397,10 @@ var ObservationTurn = class {
|
|
|
26214
26397
|
if (!this._context) throw new Error("Turn not started — call start() first");
|
|
26215
26398
|
return this._context;
|
|
26216
26399
|
}
|
|
26400
|
+
/** Whether the turn has been ended and can no longer accept steps. */
|
|
26401
|
+
get ended() {
|
|
26402
|
+
return this._ended;
|
|
26403
|
+
}
|
|
26217
26404
|
/** The current step, if one exists. */
|
|
26218
26405
|
get currentStep() {
|
|
26219
26406
|
return this._currentStep;
|
|
@@ -28041,11 +28228,19 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
28041
28228
|
const messageTokens = config.observation?.messageTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.messageTokens;
|
|
28042
28229
|
const observationTokens = config.reflection?.observationTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.observationTokens;
|
|
28043
28230
|
const isSharedBudget = config.shareTokenBudget ?? false;
|
|
28044
|
-
const
|
|
28231
|
+
const supportsDefaultTemperature = (model) => {
|
|
28232
|
+
if (model instanceof ModelByInputTokens || typeof model === "function") return false;
|
|
28233
|
+
if (typeof model === "string") return modelSupportsTemperature(model) === true;
|
|
28234
|
+
if (model && typeof model === "object" && "provider" in model && "modelId" in model && typeof model.provider === "string" && typeof model.modelId === "string") return modelSupportsTemperature(`${model.provider.split(".")[0]}/${model.modelId}`) === true;
|
|
28235
|
+
return false;
|
|
28236
|
+
};
|
|
28237
|
+
const usesDefaultOutputTokenBudget = (model) => model === void 0 || model === "default" || model instanceof ModelByInputTokens;
|
|
28045
28238
|
const observationSelectedModel = topLevelModel ?? observationConfigModel ?? reflectionConfigModel;
|
|
28046
28239
|
const reflectionSelectedModel = topLevelModel ?? reflectionConfigModel ?? observationConfigModel;
|
|
28047
|
-
const
|
|
28048
|
-
const
|
|
28240
|
+
const observationTemperature = config.observation?.modelSettings?.temperature ?? (supportsDefaultTemperature(observationModel) ? OBSERVATIONAL_MEMORY_DEFAULTS.observation.modelSettings.temperature : void 0);
|
|
28241
|
+
const observationDefaultMaxOutputTokens = config.observation?.modelSettings?.maxOutputTokens ?? (usesDefaultOutputTokenBudget(observationSelectedModel) ? OBSERVATIONAL_MEMORY_DEFAULTS.observation.modelSettings.maxOutputTokens : void 0);
|
|
28242
|
+
const reflectionTemperature = config.reflection?.modelSettings?.temperature ?? (supportsDefaultTemperature(reflectionModel) ? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.modelSettings.temperature : void 0);
|
|
28243
|
+
const reflectionDefaultMaxOutputTokens = config.reflection?.modelSettings?.maxOutputTokens ?? (usesDefaultOutputTokenBudget(reflectionSelectedModel) ? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.modelSettings.maxOutputTokens : void 0);
|
|
28049
28244
|
const totalBudget = messageTokens + observationTokens;
|
|
28050
28245
|
const userExplicitlyConfiguredAsync = config.observation?.bufferTokens !== void 0 || config.observation?.bufferActivation !== void 0 || config.reflection?.bufferActivation !== void 0;
|
|
28051
28246
|
const asyncBufferingDisabled = config.observation?.bufferTokens === false || config.scope === "resource" && !userExplicitlyConfiguredAsync;
|
|
@@ -28061,7 +28256,7 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
28061
28256
|
} : messageTokens,
|
|
28062
28257
|
shareTokenBudget: isSharedBudget,
|
|
28063
28258
|
modelSettings: {
|
|
28064
|
-
temperature:
|
|
28259
|
+
...observationTemperature !== void 0 ? { temperature: observationTemperature } : {},
|
|
28065
28260
|
...observationDefaultMaxOutputTokens !== void 0 ? { maxOutputTokens: observationDefaultMaxOutputTokens } : {}
|
|
28066
28261
|
},
|
|
28067
28262
|
providerOptions: config.observation?.providerOptions ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.providerOptions,
|
|
@@ -28087,7 +28282,7 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
28087
28282
|
observationTokens,
|
|
28088
28283
|
shareTokenBudget: isSharedBudget,
|
|
28089
28284
|
modelSettings: {
|
|
28090
|
-
temperature:
|
|
28285
|
+
...reflectionTemperature !== void 0 ? { temperature: reflectionTemperature } : {},
|
|
28091
28286
|
...reflectionDefaultMaxOutputTokens !== void 0 ? { maxOutputTokens: reflectionDefaultMaxOutputTokens } : {}
|
|
28092
28287
|
},
|
|
28093
28288
|
providerOptions: config.reflection?.providerOptions ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.providerOptions,
|
|
@@ -29942,9 +30137,11 @@ ${formattedMessages}
|
|
|
29942
30137
|
let lifecycleError;
|
|
29943
30138
|
let observationStarted = false;
|
|
29944
30139
|
let generationBefore = -1;
|
|
30140
|
+
let recordInsideLock;
|
|
29945
30141
|
try {
|
|
29946
30142
|
await this.withLock(lockKey, async () => {
|
|
29947
30143
|
const freshRecord = await this.getOrCreateRecord(threadId, resourceId);
|
|
30144
|
+
recordInsideLock = freshRecord;
|
|
29948
30145
|
generationBefore = freshRecord.generationCount;
|
|
29949
30146
|
const unobservedMessages = messages ? this.getUnobservedMessages(messages, freshRecord) : await this.loadMessagesFromStorage(threadId, resourceId, freshRecord.lastObservedAt ? new Date(freshRecord.lastObservedAt) : void 0);
|
|
29950
30147
|
if (!this.meetsObservationThreshold({
|
|
@@ -29987,7 +30184,7 @@ ${formattedMessages}
|
|
|
29987
30184
|
omDebug(`[OM:hooks] onObservationEnd hook failed after cycle failure: ${endHookError instanceof Error ? endHookError.message : String(endHookError)}`);
|
|
29988
30185
|
}
|
|
29989
30186
|
if (lifecycleError !== void 0) throw lifecycleError;
|
|
29990
|
-
const record = await this.
|
|
30187
|
+
const record = await this.getRecord(threadId, resourceId) ?? recordInsideLock;
|
|
29991
30188
|
const reflected = record.generationCount > generationBefore && generationBefore >= 0;
|
|
29992
30189
|
return {
|
|
29993
30190
|
observed,
|
|
@@ -30468,6 +30665,10 @@ var ObservationalMemoryProcessor = class {
|
|
|
30468
30665
|
if (this.turn === activeTurn) this.turn = void 0;
|
|
30469
30666
|
state.__omTurn = void 0;
|
|
30470
30667
|
}
|
|
30668
|
+
if (activeTurn?.ended || this.turn?.ended) {
|
|
30669
|
+
if (this.turn?.ended) this.turn = void 0;
|
|
30670
|
+
state.__omTurn = void 0;
|
|
30671
|
+
}
|
|
30471
30672
|
if (!this.turn || !state.__omTurn) {
|
|
30472
30673
|
if (this.turn && !state.__omTurn) await this.turn.end().catch(() => {});
|
|
30473
30674
|
this.turn = this.engine.beginTurn({
|
|
@@ -30568,11 +30769,11 @@ var ObservationalMemoryProcessor = class {
|
|
|
30568
30769
|
return this.engine.getTokenCounter().runWithModelContext(state.__omActorModelContext, async () => {
|
|
30569
30770
|
if (parseMemoryRequestContext(requestContext)?.memoryConfig?.readOnly) return messageList;
|
|
30570
30771
|
const turn = asLiveTurn(state.__omTurn) ?? this.turn;
|
|
30571
|
-
|
|
30572
|
-
|
|
30573
|
-
|
|
30574
|
-
|
|
30575
|
-
|
|
30772
|
+
const liveTurn = turn && !turn.ended ? turn : void 0;
|
|
30773
|
+
if (liveTurn) await liveTurn.end();
|
|
30774
|
+
this.turn = void 0;
|
|
30775
|
+
state.__omTurn = void 0;
|
|
30776
|
+
if (!liveTurn) {
|
|
30576
30777
|
const newOutput = messageList.get.response.db();
|
|
30577
30778
|
const messagesToSave = [...messageList.get.input.db(), ...newOutput];
|
|
30578
30779
|
if (messagesToSave.length > 0 && context.threadId) await this.engine.persistMessages(messagesToSave, context.threadId, context.resourceId);
|
|
@@ -30782,6 +30983,7 @@ const DEFAULT_MESSAGE_RANGE = {
|
|
|
30782
30983
|
};
|
|
30783
30984
|
const DEFAULT_TOP_K = 4;
|
|
30784
30985
|
const VECTOR_DELETE_BATCH_SIZE = 100;
|
|
30986
|
+
const OM_DELETE_DRAIN_TIMEOUT_MS = 1e4;
|
|
30785
30987
|
const DEFAULT_EMBEDDING_CACHE_MAX_SIZE = 1e3;
|
|
30786
30988
|
/**
|
|
30787
30989
|
* Gives Mastra agents conversation history, with optional working memory,
|
|
@@ -31233,6 +31435,8 @@ var Memory = class Memory extends MastraMemory {
|
|
|
31233
31435
|
await this.deleteStoredThread(memoryStore, threadId, thread?.resourceId);
|
|
31234
31436
|
}
|
|
31235
31437
|
async deleteStoredThread(memoryStore, threadId, resourceId) {
|
|
31438
|
+
const engine = this._omEngine ? await this._omEngine : this._omEngineInstance;
|
|
31439
|
+
if (engine && resourceId) await engine.waitForBuffering(threadId, resourceId, OM_DELETE_DRAIN_TIMEOUT_MS);
|
|
31236
31440
|
await memoryStore.deleteThread({ threadId });
|
|
31237
31441
|
if (resourceId && memoryStore.supportsObservationalMemory) await memoryStore.clearObservationalMemory(threadId, resourceId);
|
|
31238
31442
|
if (this.vector) this.trackVectorCleanup(this.deleteThreadVectors(threadId));
|
|
@@ -32966,4 +33170,4 @@ Notes:
|
|
|
32966
33170
|
//#endregion
|
|
32967
33171
|
export { formatMessagesForObserver as A, OBSERVATION_CONTINUATION_HINT as B, SUMMARIZE_THREAD_DEFAULTS as C, buildObserverPrompt as D, OBSERVER_SYSTEM_PROMPT as E, parseAnchorId as F, ModelByInputTokens as G, KnowledgeSemanticIndexCoordinator as H, stripEphemeralAnchorIds as I, publishSubconsciousActivity as J, SUBCONSCIOUS_ACTIVITY_STATE_ID as K, OBSERVATIONAL_MEMORY_DEFAULTS as L, optimizeObservationsForContext as M, parseObserverOutput as N, buildObserverSystemPrompt as O, injectAnchorIds as P, OBSERVATION_CONTEXT_INSTRUCTIONS as R, WorkingMemoryExtractor as S, TokenCounter as T, StaleKnowledgeSemanticIndexError as U, Subconscious as V, SubconsciousRemindExtractor as W, Extractor as X, renderSubconsciousActivity as Y, wrapInObservationGroup as _, extractWorkingMemoryContent as a, WorkingMemoryStateProcessor as b, getObservationsAsOf as c, combineObservationGroupRanges as d, deriveObservationGroupProvenance as f, stripObservationGroups as g, renderObservationGroupsForReflection as h, WorkingMemory as i, hasCurrentTaskSection as j, extractCurrentTask as k, ObservationalMemoryProcessor as l, reconcileObservationGroupsFromReflection as m, MessageHistory$1 as n, extractWorkingMemoryTags as o, parseObservationGroups as p, buildSubconsciousActivitySnapshot as q, SemanticRecall as r, removeWorkingMemoryTags as s, Memory as t, ObservationalMemory as u, WORKING_MEMORY_STATE_ID as v, summarizeConversation as w, deepMergeWorkingMemory as x, WORKING_MEMORY_STATE_PROCESSOR_ID as y, OBSERVATION_CONTEXT_PROMPT as z };
|
|
32968
33172
|
|
|
32969
|
-
//# sourceMappingURL=src-
|
|
33173
|
+
//# sourceMappingURL=src-CSVmHSng.js.map
|