@mastra/server 1.18.0-alpha.2 → 1.18.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/CHANGELOG.md +7 -0
- package/dist/{chunk-NTZOZIKF.cjs → chunk-GDWCOWNR.cjs} +584 -43
- package/dist/chunk-GDWCOWNR.cjs.map +1 -0
- package/dist/{chunk-DJQT32SV.cjs → chunk-HUAXEKGI.cjs} +353 -105
- package/dist/chunk-HUAXEKGI.cjs.map +1 -0
- package/dist/{chunk-FGZC4JP7.js → chunk-SDKSW2BQ.js} +571 -30
- package/dist/chunk-SDKSW2BQ.js.map +1 -0
- package/dist/{chunk-PVUR75AM.js → chunk-YUTITKH2.js} +353 -105
- package/dist/chunk-YUTITKH2.js.map +1 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/{observational-memory-UGDENJPE-NVMIXNI4.js → observational-memory-SN7GKMHZ-IWVBFBS6.js} +3 -3
- package/dist/{observational-memory-UGDENJPE-NVMIXNI4.js.map → observational-memory-SN7GKMHZ-IWVBFBS6.js.map} +1 -1
- package/dist/{observational-memory-UGDENJPE-DM3C7ZXI.cjs → observational-memory-SN7GKMHZ-WOK4TGDH.cjs} +26 -26
- package/dist/{observational-memory-UGDENJPE-DM3C7ZXI.cjs.map → observational-memory-SN7GKMHZ-WOK4TGDH.cjs.map} +1 -1
- package/dist/server/handlers/agent-builder.cjs +16 -16
- package/dist/server/handlers/agent-builder.js +1 -1
- package/dist/server/handlers.cjs +2 -2
- package/dist/server/handlers.js +1 -1
- package/dist/server/server-adapter/index.cjs +16 -16
- package/dist/server/server-adapter/index.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-DJQT32SV.cjs.map +0 -1
- package/dist/chunk-FGZC4JP7.js.map +0 -1
- package/dist/chunk-NTZOZIKF.cjs.map +0 -1
- package/dist/chunk-PVUR75AM.js.map +0 -1
|
@@ -5,7 +5,7 @@ var chunk5N66PU3H_cjs = require('./chunk-5N66PU3H.cjs');
|
|
|
5
5
|
var chunkDOHUOYZS_cjs = require('./chunk-DOHUOYZS.cjs');
|
|
6
6
|
var chunkEXKS4QPI_cjs = require('./chunk-EXKS4QPI.cjs');
|
|
7
7
|
var chunkFPURK3UW_cjs = require('./chunk-FPURK3UW.cjs');
|
|
8
|
-
var
|
|
8
|
+
var chunkHUAXEKGI_cjs = require('./chunk-HUAXEKGI.cjs');
|
|
9
9
|
var chunk3W54ZNYP_cjs = require('./chunk-3W54ZNYP.cjs');
|
|
10
10
|
var chunkHITLRKIU_cjs = require('./chunk-HITLRKIU.cjs');
|
|
11
11
|
var chunkVTPTMQFA_cjs = require('./chunk-VTPTMQFA.cjs');
|
|
@@ -16164,7 +16164,7 @@ function parseRangeFormat(cursor) {
|
|
|
16164
16164
|
}
|
|
16165
16165
|
return null;
|
|
16166
16166
|
}
|
|
16167
|
-
async function resolveCursorMessage(memory, cursor) {
|
|
16167
|
+
async function resolveCursorMessage(memory, cursor, access) {
|
|
16168
16168
|
const normalized = cursor.trim();
|
|
16169
16169
|
if (!normalized) {
|
|
16170
16170
|
throw new Error("Cursor is required");
|
|
@@ -16182,8 +16182,171 @@ async function resolveCursorMessage(memory, cursor) {
|
|
|
16182
16182
|
if (!message) {
|
|
16183
16183
|
throw new Error(`Could not resolve cursor message: ${cursor}`);
|
|
16184
16184
|
}
|
|
16185
|
+
if (access?.resourceId && message.resourceId !== access.resourceId) {
|
|
16186
|
+
throw new Error(`Could not resolve cursor message: ${cursor}`);
|
|
16187
|
+
}
|
|
16188
|
+
if (access?.threadScope && message.threadId !== access.threadScope) {
|
|
16189
|
+
throw new Error(`Could not resolve cursor message: ${cursor}`);
|
|
16190
|
+
}
|
|
16185
16191
|
return message;
|
|
16186
16192
|
}
|
|
16193
|
+
async function listThreadsForResource({
|
|
16194
|
+
memory,
|
|
16195
|
+
resourceId,
|
|
16196
|
+
currentThreadId,
|
|
16197
|
+
page = 0,
|
|
16198
|
+
limit = 20,
|
|
16199
|
+
before,
|
|
16200
|
+
after
|
|
16201
|
+
}) {
|
|
16202
|
+
if (!resourceId) {
|
|
16203
|
+
throw new Error("Resource ID is required to list threads");
|
|
16204
|
+
}
|
|
16205
|
+
const MAX_LIMIT = 50;
|
|
16206
|
+
const normalizedLimit = Math.min(Math.max(limit, 1), MAX_LIMIT);
|
|
16207
|
+
const hasDateFilter = !!(before || after);
|
|
16208
|
+
const beforeDate = before ? new Date(before) : null;
|
|
16209
|
+
const afterDate = after ? new Date(after) : null;
|
|
16210
|
+
const result = await memory.listThreads({
|
|
16211
|
+
filter: { resourceId },
|
|
16212
|
+
page: hasDateFilter ? 0 : page,
|
|
16213
|
+
perPage: hasDateFilter ? false : normalizedLimit,
|
|
16214
|
+
orderBy: { field: "updatedAt", direction: "DESC" }
|
|
16215
|
+
});
|
|
16216
|
+
let threads = result.threads;
|
|
16217
|
+
if (beforeDate) {
|
|
16218
|
+
threads = threads.filter((t) => t.createdAt < beforeDate);
|
|
16219
|
+
}
|
|
16220
|
+
if (afterDate) {
|
|
16221
|
+
threads = threads.filter((t) => t.createdAt > afterDate);
|
|
16222
|
+
}
|
|
16223
|
+
let hasMore;
|
|
16224
|
+
if (hasDateFilter) {
|
|
16225
|
+
const offset = page * normalizedLimit;
|
|
16226
|
+
hasMore = offset + normalizedLimit < threads.length;
|
|
16227
|
+
threads = threads.slice(offset, offset + normalizedLimit);
|
|
16228
|
+
} else {
|
|
16229
|
+
hasMore = result.hasMore;
|
|
16230
|
+
}
|
|
16231
|
+
if (threads.length === 0) {
|
|
16232
|
+
return {
|
|
16233
|
+
threads: "No threads found matching the criteria.",
|
|
16234
|
+
count: 0,
|
|
16235
|
+
page,
|
|
16236
|
+
hasMore: false
|
|
16237
|
+
};
|
|
16238
|
+
}
|
|
16239
|
+
const lines = [];
|
|
16240
|
+
for (const thread of threads) {
|
|
16241
|
+
const isCurrent = thread.id === currentThreadId;
|
|
16242
|
+
const title = thread.title || "(untitled)";
|
|
16243
|
+
const updated = formatTimestamp(thread.updatedAt);
|
|
16244
|
+
const created = formatTimestamp(thread.createdAt);
|
|
16245
|
+
const marker21 = isCurrent ? " \u2190 current" : "";
|
|
16246
|
+
lines.push(`- **${title}**${marker21}`);
|
|
16247
|
+
lines.push(` id: ${thread.id}`);
|
|
16248
|
+
lines.push(` updated: ${updated} | created: ${created}`);
|
|
16249
|
+
}
|
|
16250
|
+
return {
|
|
16251
|
+
threads: lines.join("\n"),
|
|
16252
|
+
count: threads.length,
|
|
16253
|
+
page,
|
|
16254
|
+
hasMore
|
|
16255
|
+
};
|
|
16256
|
+
}
|
|
16257
|
+
async function searchMessagesForResource({
|
|
16258
|
+
memory,
|
|
16259
|
+
resourceId,
|
|
16260
|
+
currentThreadId,
|
|
16261
|
+
query,
|
|
16262
|
+
topK = 10,
|
|
16263
|
+
maxTokens = DEFAULT_MAX_RESULT_TOKENS,
|
|
16264
|
+
before,
|
|
16265
|
+
after,
|
|
16266
|
+
threadScope
|
|
16267
|
+
}) {
|
|
16268
|
+
if (!memory.searchMessages) {
|
|
16269
|
+
return {
|
|
16270
|
+
results: "Search is not configured. Enable it with `retrieval: { vector: true }` and configure a vector store and embedder on your Memory instance.",
|
|
16271
|
+
count: 0
|
|
16272
|
+
};
|
|
16273
|
+
}
|
|
16274
|
+
const MAX_TOPK = 20;
|
|
16275
|
+
const clampedTopK = Math.min(Math.max(topK, 1), MAX_TOPK);
|
|
16276
|
+
const effectiveTopK = threadScope || before || after ? Math.max(clampedTopK * 3, clampedTopK + 10) : clampedTopK;
|
|
16277
|
+
const searchTopK = Math.min(MAX_TOPK, effectiveTopK);
|
|
16278
|
+
const beforeDate = before ? new Date(before) : void 0;
|
|
16279
|
+
const afterDate = after ? new Date(after) : void 0;
|
|
16280
|
+
const { results } = await memory.searchMessages({
|
|
16281
|
+
query,
|
|
16282
|
+
resourceId,
|
|
16283
|
+
topK: searchTopK,
|
|
16284
|
+
filter: {
|
|
16285
|
+
...threadScope ? { threadId: threadScope } : {},
|
|
16286
|
+
...afterDate ? { observedAfter: afterDate } : {},
|
|
16287
|
+
...beforeDate ? { observedBefore: beforeDate } : {}
|
|
16288
|
+
}
|
|
16289
|
+
});
|
|
16290
|
+
if (results.length === 0) {
|
|
16291
|
+
return {
|
|
16292
|
+
results: "No matching messages found.",
|
|
16293
|
+
count: 0
|
|
16294
|
+
};
|
|
16295
|
+
}
|
|
16296
|
+
const threadIds = [...new Set(results.map((r) => r.threadId))];
|
|
16297
|
+
const threadMap = /* @__PURE__ */ new Map();
|
|
16298
|
+
if (memory.getThreadById) {
|
|
16299
|
+
await Promise.all(
|
|
16300
|
+
threadIds.map(async (id) => {
|
|
16301
|
+
const thread = await memory.getThreadById({ threadId: id });
|
|
16302
|
+
if (thread) threadMap.set(id, thread);
|
|
16303
|
+
})
|
|
16304
|
+
);
|
|
16305
|
+
}
|
|
16306
|
+
const filteredMatches = results.filter((match) => {
|
|
16307
|
+
if (threadScope && match.threadId !== threadScope) return false;
|
|
16308
|
+
if (beforeDate && match.observedAt && match.observedAt >= beforeDate) return false;
|
|
16309
|
+
if (afterDate && match.observedAt && match.observedAt <= afterDate) return false;
|
|
16310
|
+
return true;
|
|
16311
|
+
});
|
|
16312
|
+
if (filteredMatches.length === 0) {
|
|
16313
|
+
return { results: "No matching messages found.", count: 0 };
|
|
16314
|
+
}
|
|
16315
|
+
const limitedMatches = filteredMatches.slice(0, clampedTopK);
|
|
16316
|
+
const sections = limitedMatches.map((match) => {
|
|
16317
|
+
const thread = threadMap.get(match.threadId);
|
|
16318
|
+
const title = thread?.title || "(untitled)";
|
|
16319
|
+
const isCurrentThread = match.threadId === currentThreadId;
|
|
16320
|
+
const generationLabel = isCurrentThread ? "Current thread memory" : "Older memory from another thread";
|
|
16321
|
+
const generationDetail = isCurrentThread ? "This result came from the current thread." : "This result came from an older memory generation in another thread.";
|
|
16322
|
+
const threadLine = `- thread: ${match.threadId}${thread ? ` (${title})` : ""}`;
|
|
16323
|
+
const sourceLine = match.range ? `- source: raw messages from ID ${match.range.split(":")[0] ?? "(unknown)"} through ID ${match.range.split(":")[1] ?? "(unknown)"}` : "- source: raw message range unavailable";
|
|
16324
|
+
const updatedLine = thread ? `- thread updated: ${formatTimestamp(thread.updatedAt)}` : void 0;
|
|
16325
|
+
const groupLine = match.groupId ? `- observation group: ${match.groupId}` : void 0;
|
|
16326
|
+
const scoreLine = `- score: ${match.score.toFixed(2)}`;
|
|
16327
|
+
const body = (match.text || "").trim() || "_Observation text unavailable._";
|
|
16328
|
+
return [
|
|
16329
|
+
`### ${generationLabel}`,
|
|
16330
|
+
"",
|
|
16331
|
+
generationDetail,
|
|
16332
|
+
threadLine,
|
|
16333
|
+
sourceLine,
|
|
16334
|
+
updatedLine,
|
|
16335
|
+
groupLine,
|
|
16336
|
+
scoreLine,
|
|
16337
|
+
"",
|
|
16338
|
+
"```text",
|
|
16339
|
+
body,
|
|
16340
|
+
"```"
|
|
16341
|
+
].filter(Boolean).join("\n");
|
|
16342
|
+
});
|
|
16343
|
+
const assembled = sections.join("\n\n");
|
|
16344
|
+
const { text: limited } = truncateByTokens(assembled, maxTokens);
|
|
16345
|
+
return {
|
|
16346
|
+
results: limited,
|
|
16347
|
+
count: limitedMatches.length
|
|
16348
|
+
};
|
|
16349
|
+
}
|
|
16187
16350
|
var LOW_DETAIL_PART_TOKENS = 30;
|
|
16188
16351
|
var AUTO_EXPAND_TEXT_TOKENS = 100;
|
|
16189
16352
|
var AUTO_EXPAND_TOOL_TOKENS = 20;
|
|
@@ -16193,8 +16356,8 @@ function formatTimestamp(date) {
|
|
|
16193
16356
|
return date.toISOString().replace("T", " ").replace(/\.\d{3}Z$/, "Z");
|
|
16194
16357
|
}
|
|
16195
16358
|
function truncateByTokens(text42, maxTokens, hint) {
|
|
16196
|
-
if (
|
|
16197
|
-
const truncated =
|
|
16359
|
+
if (chunkHUAXEKGI_cjs.estimateTokenCount(text42) <= maxTokens) return { text: text42, wasTruncated: false };
|
|
16360
|
+
const truncated = chunkHUAXEKGI_cjs.truncateStringByTokens(text42, maxTokens);
|
|
16198
16361
|
const suffix = hint ? ` [${hint} for more]` : "";
|
|
16199
16362
|
return { text: truncated + suffix, wasTruncated: true };
|
|
16200
16363
|
}
|
|
@@ -16227,11 +16390,11 @@ function formatMessageParts(msg, detail) {
|
|
|
16227
16390
|
} else if (partType === "tool-invocation") {
|
|
16228
16391
|
const inv = part.toolInvocation;
|
|
16229
16392
|
if (inv.state === "result") {
|
|
16230
|
-
const { value: resultValue } =
|
|
16393
|
+
const { value: resultValue } = chunkHUAXEKGI_cjs.resolveToolResultValue(
|
|
16231
16394
|
part,
|
|
16232
16395
|
inv.result
|
|
16233
16396
|
);
|
|
16234
|
-
const resultStr =
|
|
16397
|
+
const resultStr = chunkHUAXEKGI_cjs.formatToolResultForObserver(resultValue, { maxTokens: HIGH_DETAIL_TOOL_RESULT_TOKENS });
|
|
16235
16398
|
const fullText = `[Tool Result: ${inv.toolName}]
|
|
16236
16399
|
${resultStr}`;
|
|
16237
16400
|
parts.push(makePart(msg, i, "tool-result", fullText, detail));
|
|
@@ -16293,9 +16456,9 @@ function expandPriority(part) {
|
|
|
16293
16456
|
}
|
|
16294
16457
|
function renderFormattedParts(parts, timestamps, options) {
|
|
16295
16458
|
const text42 = buildRenderedText(parts, timestamps);
|
|
16296
|
-
let totalTokens =
|
|
16459
|
+
let totalTokens = chunkHUAXEKGI_cjs.estimateTokenCount(text42);
|
|
16297
16460
|
if (totalTokens > options.maxTokens) {
|
|
16298
|
-
const truncated =
|
|
16461
|
+
const truncated = chunkHUAXEKGI_cjs.truncateStringByTokens(text42, options.maxTokens);
|
|
16299
16462
|
return { text: truncated, truncated: true, tokenOffset: totalTokens - options.maxTokens };
|
|
16300
16463
|
}
|
|
16301
16464
|
const truncatedIndices = parts.map((p, i) => ({ part: p, index: i })).filter(({ part }) => part.text !== part.fullText).sort((a, b) => expandPriority(a.part) - expandPriority(b.part));
|
|
@@ -16306,8 +16469,8 @@ function renderFormattedParts(parts, timestamps, options) {
|
|
|
16306
16469
|
for (const { part, index } of truncatedIndices) {
|
|
16307
16470
|
if (remaining <= 0) break;
|
|
16308
16471
|
const maxTokens = expandLimit(part);
|
|
16309
|
-
const fullTokens =
|
|
16310
|
-
const currentTokens =
|
|
16472
|
+
const fullTokens = chunkHUAXEKGI_cjs.estimateTokenCount(part.fullText);
|
|
16473
|
+
const currentTokens = chunkHUAXEKGI_cjs.estimateTokenCount(part.text);
|
|
16311
16474
|
const targetTokens = Math.min(fullTokens, maxTokens);
|
|
16312
16475
|
const delta = targetTokens - currentTokens;
|
|
16313
16476
|
if (delta <= 0) continue;
|
|
@@ -16318,24 +16481,26 @@ function renderFormattedParts(parts, timestamps, options) {
|
|
|
16318
16481
|
const expandedLimit = Math.min(currentTokens + remaining, maxTokens);
|
|
16319
16482
|
const hint = `recall cursor="${part.messageId}" partIndex=${part.partIndex} detail="high"`;
|
|
16320
16483
|
const { text: expanded2 } = truncateByTokens(part.fullText, expandedLimit, hint);
|
|
16321
|
-
const expandedDelta =
|
|
16484
|
+
const expandedDelta = chunkHUAXEKGI_cjs.estimateTokenCount(expanded2) - currentTokens;
|
|
16322
16485
|
parts[index] = { ...part, text: expanded2 };
|
|
16323
16486
|
remaining -= expandedDelta;
|
|
16324
16487
|
}
|
|
16325
16488
|
}
|
|
16326
16489
|
const expanded = buildRenderedText(parts, timestamps);
|
|
16327
|
-
const expandedTokens =
|
|
16490
|
+
const expandedTokens = chunkHUAXEKGI_cjs.estimateTokenCount(expanded);
|
|
16328
16491
|
if (expandedTokens <= options.maxTokens) {
|
|
16329
16492
|
return { text: expanded, truncated: false, tokenOffset: 0 };
|
|
16330
16493
|
}
|
|
16331
|
-
const hardTruncated =
|
|
16494
|
+
const hardTruncated = chunkHUAXEKGI_cjs.truncateStringByTokens(expanded, options.maxTokens);
|
|
16332
16495
|
return { text: hardTruncated, truncated: true, tokenOffset: expandedTokens - options.maxTokens };
|
|
16333
16496
|
}
|
|
16334
16497
|
async function recallPart({
|
|
16335
16498
|
memory,
|
|
16336
16499
|
threadId,
|
|
16500
|
+
resourceId,
|
|
16337
16501
|
cursor,
|
|
16338
16502
|
partIndex,
|
|
16503
|
+
threadScope,
|
|
16339
16504
|
maxTokens = DEFAULT_MAX_RESULT_TOKENS
|
|
16340
16505
|
}) {
|
|
16341
16506
|
if (!memory || typeof memory.getMemoryStore !== "function") {
|
|
@@ -16344,13 +16509,10 @@ async function recallPart({
|
|
|
16344
16509
|
if (!threadId) {
|
|
16345
16510
|
throw new Error("Thread ID is required for recall");
|
|
16346
16511
|
}
|
|
16347
|
-
const resolved = await resolveCursorMessage(memory, cursor);
|
|
16512
|
+
const resolved = await resolveCursorMessage(memory, cursor, { resourceId, threadScope });
|
|
16348
16513
|
if ("hint" in resolved) {
|
|
16349
16514
|
throw new Error(resolved.hint);
|
|
16350
16515
|
}
|
|
16351
|
-
if (resolved.threadId !== threadId) {
|
|
16352
|
-
throw new Error("The requested cursor does not belong to the current thread");
|
|
16353
|
-
}
|
|
16354
16516
|
const allParts = formatMessageParts(resolved, "high");
|
|
16355
16517
|
if (allParts.length === 0) {
|
|
16356
16518
|
throw new Error(
|
|
@@ -16363,7 +16525,7 @@ async function recallPart({
|
|
|
16363
16525
|
`Part index ${partIndex} not found in message ${cursor}. Available indices: ${allParts.map((p) => p.partIndex).join(", ")}`
|
|
16364
16526
|
);
|
|
16365
16527
|
}
|
|
16366
|
-
const truncatedText =
|
|
16528
|
+
const truncatedText = chunkHUAXEKGI_cjs.truncateStringByTokens(target.text, maxTokens);
|
|
16367
16529
|
const wasTruncated = truncatedText !== target.text;
|
|
16368
16530
|
return {
|
|
16369
16531
|
text: truncatedText,
|
|
@@ -16382,6 +16544,7 @@ async function recallMessages({
|
|
|
16382
16544
|
page = 1,
|
|
16383
16545
|
limit = 20,
|
|
16384
16546
|
detail = "low",
|
|
16547
|
+
threadScope,
|
|
16385
16548
|
maxTokens = DEFAULT_MAX_RESULT_TOKENS
|
|
16386
16549
|
}) {
|
|
16387
16550
|
if (!memory) {
|
|
@@ -16398,7 +16561,7 @@ async function recallMessages({
|
|
|
16398
16561
|
const rawPage = page === 0 ? 1 : page;
|
|
16399
16562
|
const normalizedPage = Math.max(Math.min(rawPage, MAX_PAGE), -MAX_PAGE);
|
|
16400
16563
|
const normalizedLimit = Math.min(limit, MAX_LIMIT);
|
|
16401
|
-
const resolved = await resolveCursorMessage(memory, cursor);
|
|
16564
|
+
const resolved = await resolveCursorMessage(memory, cursor, { resourceId, threadScope });
|
|
16402
16565
|
if ("hint" in resolved) {
|
|
16403
16566
|
return {
|
|
16404
16567
|
messages: resolved.hint,
|
|
@@ -16414,15 +16577,27 @@ async function recallMessages({
|
|
|
16414
16577
|
};
|
|
16415
16578
|
}
|
|
16416
16579
|
const anchor = resolved;
|
|
16417
|
-
if (anchor.threadId !== threadId) {
|
|
16418
|
-
|
|
16580
|
+
if (anchor.threadId && anchor.threadId !== threadId) {
|
|
16581
|
+
return {
|
|
16582
|
+
messages: `Cursor does not belong to the active thread. Expected thread "${threadId}" but cursor "${cursor}" belongs to "${anchor.threadId}".`,
|
|
16583
|
+
count: 0,
|
|
16584
|
+
cursor,
|
|
16585
|
+
page: normalizedPage,
|
|
16586
|
+
limit: normalizedLimit,
|
|
16587
|
+
detail,
|
|
16588
|
+
hasNextPage: false,
|
|
16589
|
+
hasPrevPage: false,
|
|
16590
|
+
truncated: false,
|
|
16591
|
+
tokenOffset: 0
|
|
16592
|
+
};
|
|
16419
16593
|
}
|
|
16594
|
+
const resolvedThreadId = threadId;
|
|
16420
16595
|
const isForward = normalizedPage > 0;
|
|
16421
16596
|
const pageIndex = Math.max(Math.abs(normalizedPage), 1) - 1;
|
|
16422
16597
|
const skip = pageIndex * normalizedLimit;
|
|
16423
16598
|
const fetchCount = skip + normalizedLimit + 1;
|
|
16424
16599
|
const result = await memory.recall({
|
|
16425
|
-
threadId,
|
|
16600
|
+
threadId: resolvedThreadId,
|
|
16426
16601
|
resourceId,
|
|
16427
16602
|
page: 0,
|
|
16428
16603
|
perPage: fetchCount,
|
|
@@ -16505,55 +16680,233 @@ High detail returns 1 part at a time. To continue: ${hints.join(", or ")}.`;
|
|
|
16505
16680
|
tokenOffset: rendered.tokenOffset
|
|
16506
16681
|
};
|
|
16507
16682
|
}
|
|
16508
|
-
|
|
16683
|
+
async function recallThreadFromStart({
|
|
16684
|
+
memory,
|
|
16685
|
+
threadId,
|
|
16686
|
+
resourceId,
|
|
16687
|
+
page = 1,
|
|
16688
|
+
limit = 20,
|
|
16689
|
+
detail = "low",
|
|
16690
|
+
maxTokens = DEFAULT_MAX_RESULT_TOKENS
|
|
16691
|
+
}) {
|
|
16692
|
+
if (!memory) {
|
|
16693
|
+
throw new Error("Memory instance is required for recall");
|
|
16694
|
+
}
|
|
16695
|
+
if (!threadId) {
|
|
16696
|
+
throw new Error("Thread ID is required for recall");
|
|
16697
|
+
}
|
|
16698
|
+
if (resourceId && memory.getThreadById) {
|
|
16699
|
+
const thread = await memory.getThreadById({ threadId });
|
|
16700
|
+
if (!thread || thread.resourceId !== resourceId) {
|
|
16701
|
+
throw new Error("Thread not found");
|
|
16702
|
+
}
|
|
16703
|
+
}
|
|
16704
|
+
const MAX_PAGE = 50;
|
|
16705
|
+
const MAX_LIMIT = 20;
|
|
16706
|
+
const normalizedPage = Math.max(Math.min(page, MAX_PAGE), 1);
|
|
16707
|
+
const normalizedLimit = Math.min(Math.max(limit, 1), MAX_LIMIT);
|
|
16708
|
+
const pageIndex = normalizedPage - 1;
|
|
16709
|
+
const fetchCount = pageIndex * normalizedLimit + normalizedLimit + 1;
|
|
16710
|
+
const result = await memory.recall({
|
|
16711
|
+
threadId,
|
|
16712
|
+
resourceId,
|
|
16713
|
+
page: 0,
|
|
16714
|
+
perPage: fetchCount,
|
|
16715
|
+
orderBy: { field: "createdAt", direction: "ASC" }
|
|
16716
|
+
});
|
|
16717
|
+
const visibleMessages = result.messages.filter(hasVisibleParts);
|
|
16718
|
+
const total = visibleMessages.length;
|
|
16719
|
+
const skip = pageIndex * normalizedLimit;
|
|
16720
|
+
const hasMore = total > skip + normalizedLimit;
|
|
16721
|
+
const messages = visibleMessages.slice(skip, skip + normalizedLimit);
|
|
16722
|
+
const allParts = [];
|
|
16723
|
+
const timestamps = /* @__PURE__ */ new Map();
|
|
16724
|
+
for (const msg of messages) {
|
|
16725
|
+
timestamps.set(msg.id, msg.createdAt);
|
|
16726
|
+
allParts.push(...formatMessageParts(msg, detail));
|
|
16727
|
+
}
|
|
16728
|
+
const rendered = renderFormattedParts(allParts, timestamps, { maxTokens });
|
|
16729
|
+
return {
|
|
16730
|
+
messages: rendered.text || "(no messages in this thread)",
|
|
16731
|
+
count: messages.length,
|
|
16732
|
+
cursor: messages[0]?.id || "",
|
|
16733
|
+
page: normalizedPage,
|
|
16734
|
+
limit: normalizedLimit,
|
|
16735
|
+
detail,
|
|
16736
|
+
hasNextPage: hasMore,
|
|
16737
|
+
hasPrevPage: pageIndex > 0,
|
|
16738
|
+
truncated: rendered.truncated,
|
|
16739
|
+
tokenOffset: rendered.tokenOffset
|
|
16740
|
+
};
|
|
16741
|
+
}
|
|
16742
|
+
var recallTool = (_memoryConfig, options) => {
|
|
16743
|
+
const retrievalScope = options?.retrievalScope ?? "thread";
|
|
16744
|
+
const isResourceScope = retrievalScope === "resource";
|
|
16745
|
+
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. If you pass only a cursor, it must belong to the current thread. 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. Use mode="search" to find messages by content in this thread. Use mode="threads" to get the current thread's ID and title.`;
|
|
16509
16746
|
return tools.createTool({
|
|
16510
16747
|
id: "recall",
|
|
16511
|
-
description
|
|
16748
|
+
description,
|
|
16512
16749
|
inputSchema: zod.z.object({
|
|
16513
|
-
|
|
16750
|
+
...isResourceScope ? {
|
|
16751
|
+
mode: zod.z.enum(["messages", "threads", "search"]).optional().describe(
|
|
16752
|
+
'What to retrieve. "messages" (default) pages through message history. "threads" lists all threads for the current user. "search" finds messages by semantic similarity across all threads.'
|
|
16753
|
+
),
|
|
16754
|
+
threadId: zod.z.string().min(1).optional().describe('Browse a different thread. Use mode="threads" first to discover thread IDs.'),
|
|
16755
|
+
before: zod.z.string().optional().describe(
|
|
16756
|
+
'For mode="threads": only show threads created before this date. ISO 8601 or natural date string (e.g. "2026-03-15", "2026-03-10T00:00:00Z").'
|
|
16757
|
+
),
|
|
16758
|
+
after: zod.z.string().optional().describe(
|
|
16759
|
+
'For mode="threads": only show threads created after this date. ISO 8601 or natural date string (e.g. "2026-03-01", "2026-03-10T00:00:00Z").'
|
|
16760
|
+
)
|
|
16761
|
+
} : {
|
|
16762
|
+
mode: zod.z.enum(["messages", "threads", "search"]).optional().describe(
|
|
16763
|
+
'What to retrieve. "messages" (default) pages through message history. "threads" returns info about the current thread. "search" finds messages by semantic similarity in this thread.'
|
|
16764
|
+
)
|
|
16765
|
+
},
|
|
16766
|
+
query: zod.z.string().min(1).optional().describe('Search query for mode="search". Finds messages semantically similar to this text.'),
|
|
16767
|
+
cursor: zod.z.string().min(1).optional().describe(
|
|
16768
|
+
'A message ID to use as the pagination cursor. For mode="messages", provide either cursor or threadId. If only cursor is provided, it must belong to the current thread. Extract it from the start or end of an observation group range.'
|
|
16769
|
+
),
|
|
16514
16770
|
page: zod.z.number().int().min(-50).max(50).optional().describe(
|
|
16515
|
-
"Pagination offset
|
|
16771
|
+
"Pagination offset. For messages: positive pages move forward from cursor, negative move backward. For threads: page number (0-indexed). 0 is treated as 1 for messages."
|
|
16516
16772
|
),
|
|
16517
|
-
limit: zod.z.number().int().positive().max(20).optional().describe("Maximum number of
|
|
16773
|
+
limit: zod.z.number().int().positive().max(20).optional().describe("Maximum number of items to return per page. Defaults to 20."),
|
|
16518
16774
|
detail: zod.z.enum(["low", "high"]).optional().describe(
|
|
16519
|
-
'Detail level. "low" (default) returns truncated text and tool names. "high" returns full content with tool args/results.'
|
|
16775
|
+
'Detail level for messages. "low" (default) returns truncated text and tool names. "high" returns full content with tool args/results.'
|
|
16520
16776
|
),
|
|
16521
16777
|
partIndex: zod.z.number().int().min(0).optional().describe(
|
|
16522
16778
|
"Fetch a single part from the cursor message by its positional index. When provided, returns only that part at high detail. Indices are shown as [p0], [p1], etc. in recall results."
|
|
16523
16779
|
)
|
|
16524
16780
|
}),
|
|
16525
16781
|
execute: async ({
|
|
16782
|
+
mode,
|
|
16783
|
+
query,
|
|
16526
16784
|
cursor,
|
|
16785
|
+
threadId: explicitThreadId,
|
|
16527
16786
|
page,
|
|
16528
16787
|
limit,
|
|
16529
16788
|
detail,
|
|
16530
|
-
partIndex
|
|
16789
|
+
partIndex,
|
|
16790
|
+
before,
|
|
16791
|
+
after
|
|
16531
16792
|
}, context2) => {
|
|
16532
16793
|
const memory = context2?.memory;
|
|
16533
|
-
const
|
|
16794
|
+
const currentThreadId = context2?.agent?.threadId;
|
|
16534
16795
|
const resourceId = context2?.agent?.resourceId;
|
|
16535
16796
|
if (!memory) {
|
|
16536
16797
|
throw new Error("Memory instance is required for recall");
|
|
16537
16798
|
}
|
|
16538
|
-
if (
|
|
16799
|
+
if (mode === "search") {
|
|
16800
|
+
if (!query) {
|
|
16801
|
+
throw new Error('query is required for mode="search"');
|
|
16802
|
+
}
|
|
16803
|
+
if (!resourceId) {
|
|
16804
|
+
throw new Error("Resource ID is required for recall");
|
|
16805
|
+
}
|
|
16806
|
+
return searchMessagesForResource({
|
|
16807
|
+
memory,
|
|
16808
|
+
resourceId,
|
|
16809
|
+
currentThreadId: currentThreadId || void 0,
|
|
16810
|
+
query,
|
|
16811
|
+
topK: limit ?? 10,
|
|
16812
|
+
before,
|
|
16813
|
+
after,
|
|
16814
|
+
threadScope: !isResourceScope ? currentThreadId || void 0 : void 0
|
|
16815
|
+
});
|
|
16816
|
+
}
|
|
16817
|
+
if (mode === "threads") {
|
|
16818
|
+
if (!isResourceScope) {
|
|
16819
|
+
if (!currentThreadId || !memory.getThreadById) {
|
|
16820
|
+
return { error: "Could not resolve current thread." };
|
|
16821
|
+
}
|
|
16822
|
+
const thread = await memory.getThreadById({ threadId: currentThreadId });
|
|
16823
|
+
if (!thread) {
|
|
16824
|
+
return { error: "Could not resolve current thread." };
|
|
16825
|
+
}
|
|
16826
|
+
return {
|
|
16827
|
+
threads: `- **${thread.title || "(untitled)"}** \u2190 current
|
|
16828
|
+
id: ${thread.id}
|
|
16829
|
+
updated: ${formatTimestamp(thread.updatedAt)} | created: ${formatTimestamp(thread.createdAt)}`,
|
|
16830
|
+
count: 1,
|
|
16831
|
+
page: 0,
|
|
16832
|
+
hasMore: false
|
|
16833
|
+
};
|
|
16834
|
+
}
|
|
16835
|
+
if (!resourceId) {
|
|
16836
|
+
throw new Error("Resource ID is required for recall");
|
|
16837
|
+
}
|
|
16838
|
+
return listThreadsForResource({
|
|
16839
|
+
memory,
|
|
16840
|
+
resourceId,
|
|
16841
|
+
currentThreadId: currentThreadId || "",
|
|
16842
|
+
page: page ?? 0,
|
|
16843
|
+
limit: limit ?? 20,
|
|
16844
|
+
before,
|
|
16845
|
+
after
|
|
16846
|
+
});
|
|
16847
|
+
}
|
|
16848
|
+
const hasExplicitThreadId = typeof explicitThreadId === "string" && explicitThreadId.length > 0;
|
|
16849
|
+
const hasCursor = typeof cursor === "string" && cursor.length > 0;
|
|
16850
|
+
if (!hasExplicitThreadId && !hasCursor) {
|
|
16851
|
+
throw new Error('Either cursor or threadId is required for mode="messages"');
|
|
16852
|
+
}
|
|
16853
|
+
let targetThreadId;
|
|
16854
|
+
let threadScope;
|
|
16855
|
+
if (!isResourceScope) {
|
|
16856
|
+
targetThreadId = currentThreadId;
|
|
16857
|
+
threadScope = currentThreadId || void 0;
|
|
16858
|
+
} else if (hasExplicitThreadId) {
|
|
16859
|
+
if (!resourceId) {
|
|
16860
|
+
throw new Error("Resource ID is required for recall");
|
|
16861
|
+
}
|
|
16862
|
+
if (!memory.getThreadById) {
|
|
16863
|
+
throw new Error("Memory instance cannot verify thread access for recall");
|
|
16864
|
+
}
|
|
16865
|
+
const thread = await memory.getThreadById({ threadId: explicitThreadId });
|
|
16866
|
+
if (!thread || thread.resourceId !== resourceId) {
|
|
16867
|
+
throw new Error("Thread does not belong to the active resource");
|
|
16868
|
+
}
|
|
16869
|
+
targetThreadId = thread.id;
|
|
16870
|
+
threadScope = thread.id;
|
|
16871
|
+
} else {
|
|
16872
|
+
targetThreadId = currentThreadId;
|
|
16873
|
+
threadScope = currentThreadId || void 0;
|
|
16874
|
+
}
|
|
16875
|
+
if (hasCursor && !hasExplicitThreadId && !currentThreadId) {
|
|
16876
|
+
throw new Error("Current thread is required when browsing by cursor");
|
|
16877
|
+
}
|
|
16878
|
+
if (!targetThreadId) {
|
|
16539
16879
|
throw new Error("Thread ID is required for recall");
|
|
16540
16880
|
}
|
|
16881
|
+
if (!cursor) {
|
|
16882
|
+
return recallThreadFromStart({
|
|
16883
|
+
memory,
|
|
16884
|
+
threadId: targetThreadId,
|
|
16885
|
+
resourceId: isResourceScope ? resourceId : void 0,
|
|
16886
|
+
page: page ?? 1,
|
|
16887
|
+
limit: limit ?? 20,
|
|
16888
|
+
detail: detail ?? "low"
|
|
16889
|
+
});
|
|
16890
|
+
}
|
|
16541
16891
|
if (partIndex !== void 0 && partIndex !== null) {
|
|
16542
16892
|
return recallPart({
|
|
16543
16893
|
memory,
|
|
16544
|
-
threadId,
|
|
16894
|
+
threadId: targetThreadId,
|
|
16895
|
+
resourceId: isResourceScope ? resourceId : void 0,
|
|
16545
16896
|
cursor,
|
|
16546
|
-
partIndex
|
|
16897
|
+
partIndex,
|
|
16898
|
+
threadScope
|
|
16547
16899
|
});
|
|
16548
16900
|
}
|
|
16549
16901
|
return recallMessages({
|
|
16550
16902
|
memory,
|
|
16551
|
-
threadId,
|
|
16552
|
-
resourceId,
|
|
16903
|
+
threadId: targetThreadId,
|
|
16904
|
+
resourceId: isResourceScope ? resourceId : void 0,
|
|
16553
16905
|
cursor,
|
|
16554
16906
|
page,
|
|
16555
16907
|
limit,
|
|
16556
|
-
detail: detail ?? "low"
|
|
16908
|
+
detail: detail ?? "low",
|
|
16909
|
+
threadScope
|
|
16557
16910
|
});
|
|
16558
16911
|
}
|
|
16559
16912
|
});
|
|
@@ -16805,6 +17158,19 @@ var Memory = class extends memory.MastraMemory {
|
|
|
16805
17158
|
observationalMemory: config.options?.observationalMemory
|
|
16806
17159
|
});
|
|
16807
17160
|
this.threadConfig = mergedConfig;
|
|
17161
|
+
const omConfig = normalizeObservationalMemoryConfig(mergedConfig.observationalMemory);
|
|
17162
|
+
if (omConfig?.retrieval && typeof omConfig.retrieval === "object" && omConfig.retrieval.vector) {
|
|
17163
|
+
if (!this.vector) {
|
|
17164
|
+
throw new Error(
|
|
17165
|
+
"`retrieval: { vector: true }` requires a vector store. Pass a `vector` option to your Memory instance."
|
|
17166
|
+
);
|
|
17167
|
+
}
|
|
17168
|
+
if (!this.embedder) {
|
|
17169
|
+
throw new Error(
|
|
17170
|
+
"`retrieval: { vector: true }` requires an embedder. Pass an `embedder` option to your Memory instance."
|
|
17171
|
+
);
|
|
17172
|
+
}
|
|
17173
|
+
}
|
|
16808
17174
|
}
|
|
16809
17175
|
/**
|
|
16810
17176
|
* Gets the memory storage domain, throwing if not available.
|
|
@@ -17193,7 +17559,7 @@ ${workingMemory}`;
|
|
|
17193
17559
|
}
|
|
17194
17560
|
return chunks;
|
|
17195
17561
|
}
|
|
17196
|
-
hasher =
|
|
17562
|
+
hasher = chunkHUAXEKGI_cjs.e();
|
|
17197
17563
|
// embedding is computationally expensive so cache content -> embeddings/chunks
|
|
17198
17564
|
embeddingCache = /* @__PURE__ */ new Map();
|
|
17199
17565
|
firstEmbed;
|
|
@@ -17574,13 +17940,17 @@ ${workingMemory}`;
|
|
|
17574
17940
|
"Observational memory requires @mastra/core support for request-response-id-rotation. Please bump @mastra/core to a newer version."
|
|
17575
17941
|
);
|
|
17576
17942
|
}
|
|
17577
|
-
const { ObservationalMemory: OMClass } = await import('./observational-memory-
|
|
17943
|
+
const { ObservationalMemory: OMClass } = await import('./observational-memory-SN7GKMHZ-WOK4TGDH.cjs');
|
|
17944
|
+
const onIndexObservations = this.hasRetrievalSearch(omConfig.retrieval) ? async (observation) => {
|
|
17945
|
+
await this.indexObservation(observation);
|
|
17946
|
+
} : void 0;
|
|
17578
17947
|
return new OMClass({
|
|
17579
17948
|
storage: memoryStore,
|
|
17580
17949
|
scope: omConfig.scope,
|
|
17581
17950
|
retrieval: omConfig.retrieval,
|
|
17582
17951
|
shareTokenBudget: omConfig.shareTokenBudget,
|
|
17583
17952
|
model: omConfig.model,
|
|
17953
|
+
onIndexObservations,
|
|
17584
17954
|
observation: omConfig.observation ? {
|
|
17585
17955
|
model: omConfig.observation.model,
|
|
17586
17956
|
messageTokens: omConfig.observation.messageTokens,
|
|
@@ -17716,6 +18086,176 @@ Notes:
|
|
|
17716
18086
|
const isMDWorkingMemory = !(`schema` in config.workingMemory) && (typeof config.workingMemory.template === `string` || config.workingMemory.template) && config.workingMemory;
|
|
17717
18087
|
return Boolean(isMDWorkingMemory && isMDWorkingMemory.version === `vnext`);
|
|
17718
18088
|
}
|
|
18089
|
+
getObservationEmbeddingIndexName(dimensions) {
|
|
18090
|
+
const defaultDimensions = 384;
|
|
18091
|
+
const usedDimensions = dimensions ?? defaultDimensions;
|
|
18092
|
+
const separator = this.vector?.indexSeparator ?? "_";
|
|
18093
|
+
return `memory${separator}observations${separator}${usedDimensions}`;
|
|
18094
|
+
}
|
|
18095
|
+
async createObservationEmbeddingIndex(dimensions) {
|
|
18096
|
+
const defaultDimensions = 384;
|
|
18097
|
+
const usedDimensions = dimensions ?? defaultDimensions;
|
|
18098
|
+
const indexName = this.getObservationEmbeddingIndexName(dimensions);
|
|
18099
|
+
if (typeof this.vector === `undefined`) {
|
|
18100
|
+
throw new Error(
|
|
18101
|
+
`Tried to create observation embedding index but no vector db is attached to this Memory instance.`
|
|
18102
|
+
);
|
|
18103
|
+
}
|
|
18104
|
+
await this.vector.createIndex({
|
|
18105
|
+
indexName,
|
|
18106
|
+
dimension: usedDimensions
|
|
18107
|
+
});
|
|
18108
|
+
return { indexName };
|
|
18109
|
+
}
|
|
18110
|
+
/**
|
|
18111
|
+
* Search observation groups across threads by semantic similarity.
|
|
18112
|
+
* Requires a vector store and embedder to be configured.
|
|
18113
|
+
*/
|
|
18114
|
+
async searchMessages({
|
|
18115
|
+
query,
|
|
18116
|
+
resourceId,
|
|
18117
|
+
topK = 10,
|
|
18118
|
+
filter: filter32
|
|
18119
|
+
}) {
|
|
18120
|
+
if (!this.vector) {
|
|
18121
|
+
throw new Error("searchMessages requires a vector store. Configure vector and embedder on your Memory instance.");
|
|
18122
|
+
}
|
|
18123
|
+
const { embeddings, dimension } = await this.embedMessageContent(query);
|
|
18124
|
+
const { indexName } = await this.createObservationEmbeddingIndex(dimension);
|
|
18125
|
+
const vectorFilter = { resource_id: resourceId };
|
|
18126
|
+
if (filter32?.threadId) {
|
|
18127
|
+
vectorFilter.thread_id = filter32.threadId;
|
|
18128
|
+
}
|
|
18129
|
+
if (filter32?.observedAfter || filter32?.observedBefore) {
|
|
18130
|
+
vectorFilter.observed_at = {
|
|
18131
|
+
...filter32.observedAfter ? { $gt: filter32.observedAfter.toISOString() } : {},
|
|
18132
|
+
...filter32.observedBefore ? { $lt: filter32.observedBefore.toISOString() } : {}
|
|
18133
|
+
};
|
|
18134
|
+
}
|
|
18135
|
+
const queryResults = [];
|
|
18136
|
+
await Promise.all(
|
|
18137
|
+
embeddings.map(async (embedding) => {
|
|
18138
|
+
const results2 = await this.vector.query({
|
|
18139
|
+
indexName,
|
|
18140
|
+
queryVector: embedding,
|
|
18141
|
+
topK,
|
|
18142
|
+
filter: vectorFilter
|
|
18143
|
+
});
|
|
18144
|
+
for (const r of results2) {
|
|
18145
|
+
if (!r.metadata?.thread_id) {
|
|
18146
|
+
continue;
|
|
18147
|
+
}
|
|
18148
|
+
const groupId = typeof r.metadata.group_id === "string" ? r.metadata.group_id : void 0;
|
|
18149
|
+
if (!groupId) {
|
|
18150
|
+
continue;
|
|
18151
|
+
}
|
|
18152
|
+
queryResults.push({
|
|
18153
|
+
threadId: r.metadata.thread_id,
|
|
18154
|
+
score: r.score,
|
|
18155
|
+
groupId,
|
|
18156
|
+
range: typeof r.metadata.range === "string" ? r.metadata.range : void 0,
|
|
18157
|
+
text: typeof r.metadata.text === "string" ? r.metadata.text : void 0,
|
|
18158
|
+
observedAt: typeof r.metadata.observed_at === "string" || r.metadata.observed_at instanceof Date ? new Date(r.metadata.observed_at) : void 0
|
|
18159
|
+
});
|
|
18160
|
+
}
|
|
18161
|
+
})
|
|
18162
|
+
);
|
|
18163
|
+
const bestByGroup = /* @__PURE__ */ new Map();
|
|
18164
|
+
for (const result of queryResults) {
|
|
18165
|
+
if (!result.groupId) {
|
|
18166
|
+
continue;
|
|
18167
|
+
}
|
|
18168
|
+
const existing = bestByGroup.get(result.groupId);
|
|
18169
|
+
if (!existing || result.score > existing.score) {
|
|
18170
|
+
bestByGroup.set(result.groupId, result);
|
|
18171
|
+
}
|
|
18172
|
+
}
|
|
18173
|
+
const results = [...bestByGroup.values()].sort((a, b) => b.score - a.score);
|
|
18174
|
+
return { results };
|
|
18175
|
+
}
|
|
18176
|
+
/**
|
|
18177
|
+
* Index a single observation group into the observation vector store.
|
|
18178
|
+
*/
|
|
18179
|
+
async indexObservation({
|
|
18180
|
+
text: text42,
|
|
18181
|
+
groupId,
|
|
18182
|
+
range,
|
|
18183
|
+
threadId,
|
|
18184
|
+
resourceId,
|
|
18185
|
+
observedAt
|
|
18186
|
+
}) {
|
|
18187
|
+
if (!this.vector || !this.embedder) return;
|
|
18188
|
+
const embedResult = await this.embedMessageContent(text42);
|
|
18189
|
+
if (embedResult.embeddings.length === 0 || embedResult.dimension === void 0) {
|
|
18190
|
+
return;
|
|
18191
|
+
}
|
|
18192
|
+
const { indexName } = await this.createObservationEmbeddingIndex(embedResult.dimension);
|
|
18193
|
+
await this.vector.upsert({
|
|
18194
|
+
indexName,
|
|
18195
|
+
vectors: embedResult.embeddings,
|
|
18196
|
+
metadata: embedResult.chunks.map((chunk) => ({
|
|
18197
|
+
group_id: groupId,
|
|
18198
|
+
range,
|
|
18199
|
+
thread_id: threadId,
|
|
18200
|
+
resource_id: resourceId,
|
|
18201
|
+
observed_at: observedAt?.toISOString(),
|
|
18202
|
+
text: chunk
|
|
18203
|
+
}))
|
|
18204
|
+
});
|
|
18205
|
+
}
|
|
18206
|
+
/**
|
|
18207
|
+
* Index a list of messages directly (without querying storage).
|
|
18208
|
+
* Used by observe-time indexing to vectorize newly-observed messages.
|
|
18209
|
+
*/
|
|
18210
|
+
async indexMessagesList(messages) {
|
|
18211
|
+
if (!this.vector || !this.embedder) return;
|
|
18212
|
+
const embeddingData = [];
|
|
18213
|
+
let dimension;
|
|
18214
|
+
await Promise.all(
|
|
18215
|
+
messages.map(async (message) => {
|
|
18216
|
+
let textForEmbedding = null;
|
|
18217
|
+
if (message.content.content && typeof message.content.content === "string" && message.content.content.trim() !== "") {
|
|
18218
|
+
textForEmbedding = message.content.content;
|
|
18219
|
+
} else if (message.content.parts && message.content.parts.length > 0) {
|
|
18220
|
+
const joined = message.content.parts.filter((part) => part.type === "text").map((part) => part.text).join(" ").trim();
|
|
18221
|
+
if (joined) textForEmbedding = joined;
|
|
18222
|
+
}
|
|
18223
|
+
if (!textForEmbedding) return;
|
|
18224
|
+
const embedResult = await this.embedMessageContent(textForEmbedding);
|
|
18225
|
+
dimension = embedResult.dimension;
|
|
18226
|
+
embeddingData.push({
|
|
18227
|
+
embeddings: embedResult.embeddings,
|
|
18228
|
+
metadata: embedResult.chunks.map(() => ({
|
|
18229
|
+
message_id: message.id,
|
|
18230
|
+
thread_id: message.threadId,
|
|
18231
|
+
resource_id: message.resourceId
|
|
18232
|
+
}))
|
|
18233
|
+
});
|
|
18234
|
+
})
|
|
18235
|
+
);
|
|
18236
|
+
if (embeddingData.length > 0 && dimension !== void 0) {
|
|
18237
|
+
const { indexName } = await this.createEmbeddingIndex(dimension);
|
|
18238
|
+
const allVectors = [];
|
|
18239
|
+
const allMetadata = [];
|
|
18240
|
+
for (const data of embeddingData) {
|
|
18241
|
+
allVectors.push(...data.embeddings);
|
|
18242
|
+
allMetadata.push(...data.metadata);
|
|
18243
|
+
}
|
|
18244
|
+
await this.vector.upsert({
|
|
18245
|
+
indexName,
|
|
18246
|
+
vectors: allVectors,
|
|
18247
|
+
metadata: allMetadata
|
|
18248
|
+
});
|
|
18249
|
+
}
|
|
18250
|
+
}
|
|
18251
|
+
/**
|
|
18252
|
+
* Check whether retrieval search (vector-based) is enabled.
|
|
18253
|
+
* Returns true when `retrieval: { vector: true }` and Memory has vector + embedder configured.
|
|
18254
|
+
*/
|
|
18255
|
+
hasRetrievalSearch(retrieval) {
|
|
18256
|
+
if (!retrieval || retrieval === true) return false;
|
|
18257
|
+
return !!retrieval.vector && !!this.vector && !!this.embedder;
|
|
18258
|
+
}
|
|
17719
18259
|
listTools(config) {
|
|
17720
18260
|
const mergedConfig = this.getMergedThreadConfig(config);
|
|
17721
18261
|
const tools = {};
|
|
@@ -17723,8 +18263,9 @@ Notes:
|
|
|
17723
18263
|
tools.updateWorkingMemory = this.isVNextWorkingMemoryConfig(mergedConfig) ? __experimental_updateWorkingMemoryToolVNext(mergedConfig) : updateWorkingMemoryTool(mergedConfig);
|
|
17724
18264
|
}
|
|
17725
18265
|
const omConfig = normalizeObservationalMemoryConfig(mergedConfig.observationalMemory);
|
|
17726
|
-
if (omConfig?.retrieval
|
|
17727
|
-
|
|
18266
|
+
if (omConfig?.retrieval) {
|
|
18267
|
+
const retrievalScope = typeof omConfig.retrieval === "object" ? omConfig.retrieval.scope ?? "resource" : "resource";
|
|
18268
|
+
tools.recall = recallTool(mergedConfig, { retrievalScope });
|
|
17728
18269
|
}
|
|
17729
18270
|
return tools;
|
|
17730
18271
|
}
|
|
@@ -18287,7 +18828,7 @@ Notes:
|
|
|
18287
18828
|
if (!effectiveConfig) return null;
|
|
18288
18829
|
const engine = await this.omEngine;
|
|
18289
18830
|
if (!engine) return null;
|
|
18290
|
-
const { ObservationalMemoryProcessor } = await import('./observational-memory-
|
|
18831
|
+
const { ObservationalMemoryProcessor } = await import('./observational-memory-SN7GKMHZ-WOK4TGDH.cjs');
|
|
18291
18832
|
return new ObservationalMemoryProcessor(engine, this);
|
|
18292
18833
|
}
|
|
18293
18834
|
};
|
|
@@ -29503,5 +30044,5 @@ exports.START_ASYNC_AGENT_BUILDER_ACTION_ROUTE = START_ASYNC_AGENT_BUILDER_ACTIO
|
|
|
29503
30044
|
exports.STREAM_AGENT_BUILDER_ACTION_ROUTE = STREAM_AGENT_BUILDER_ACTION_ROUTE;
|
|
29504
30045
|
exports.STREAM_LEGACY_AGENT_BUILDER_ACTION_ROUTE = STREAM_LEGACY_AGENT_BUILDER_ACTION_ROUTE;
|
|
29505
30046
|
exports.agent_builder_exports = agent_builder_exports;
|
|
29506
|
-
//# sourceMappingURL=chunk-
|
|
29507
|
-
//# sourceMappingURL=chunk-
|
|
30047
|
+
//# sourceMappingURL=chunk-GDWCOWNR.cjs.map
|
|
30048
|
+
//# sourceMappingURL=chunk-GDWCOWNR.cjs.map
|