@mastra/memory 1.33.0 → 1.34.0-alpha.1
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-agents-human-in-the-loop.md +6 -4
- package/dist/docs/references/reference-memory-observational-memory.md +3 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/processors/index.cjs +1 -1
- package/dist/processors/index.js +1 -1
- package/dist/processors/observational-memory/observation-groups.d.ts.map +1 -1
- package/dist/processors/observational-memory/repro-capture.d.ts.map +1 -1
- package/dist/processors/observational-memory/subconscious/activity.d.ts.map +1 -1
- package/dist/processors/observational-memory/subconscious/remind-questions.d.ts.map +1 -1
- package/dist/processors/observational-memory/temporary-memory.d.ts.map +1 -1
- package/dist/processors/observational-memory/token-counter.d.ts +6 -0
- package/dist/processors/observational-memory/token-counter.d.ts.map +1 -1
- package/dist/{src-BdfOygyn.js → src-BYAwbfUo.js} +218 -41
- package/dist/src-BYAwbfUo.js.map +1 -0
- package/dist/{src-CMESxrGy.cjs → src-Cm4sUXMu.cjs} +218 -42
- package/dist/src-Cm4sUXMu.cjs.map +1 -0
- package/dist/tools/om-tools.d.ts +22 -0
- package/dist/tools/om-tools.d.ts.map +1 -1
- package/package.json +6 -6
- package/dist/src-BdfOygyn.js.map +0 -1
- package/dist/src-CMESxrGy.cjs.map +0 -1
|
@@ -29,8 +29,6 @@ var __toESM$1 = (mod, isNodeMode, target) => (target = mod != null ? __create$1(
|
|
|
29
29
|
enumerable: true
|
|
30
30
|
}) : target, mod));
|
|
31
31
|
//#endregion
|
|
32
|
-
let crypto$1 = require("crypto");
|
|
33
|
-
crypto$1 = __toESM$1(crypto$1, 1);
|
|
34
32
|
let zod_v3 = require("zod/v3");
|
|
35
33
|
let zod = require("zod");
|
|
36
34
|
let zod_v4 = require("zod/v4");
|
|
@@ -53,6 +51,7 @@ let _mastra_core_tools = require("@mastra/core/tools");
|
|
|
53
51
|
let _mastra_core_request_context = require("@mastra/core/request-context");
|
|
54
52
|
let _mastra_core_llm = require("@mastra/core/llm");
|
|
55
53
|
let async_hooks = require("async_hooks");
|
|
54
|
+
let crypto$1 = require("crypto");
|
|
56
55
|
let probe_image_size_sync_js = require("probe-image-size/sync.js");
|
|
57
56
|
probe_image_size_sync_js = __toESM$1(probe_image_size_sync_js, 1);
|
|
58
57
|
let _mastra_core_schema = require("@mastra/core/schema");
|
|
@@ -15693,6 +15692,10 @@ if (OM_DEBUG_LOG) {
|
|
|
15693
15692
|
//#endregion
|
|
15694
15693
|
//#region src/processors/observational-memory/subconscious/activity.ts
|
|
15695
15694
|
const SUBCONSCIOUS_ACTIVITY_STATE_ID = "subconscious-activity";
|
|
15695
|
+
async function hashContents(contents) {
|
|
15696
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(contents));
|
|
15697
|
+
return Buffer.from(digest).toString("hex");
|
|
15698
|
+
}
|
|
15696
15699
|
async function getActivityTarget(store, event, scope) {
|
|
15697
15700
|
if (event.recordType === "node") {
|
|
15698
15701
|
const node = await store.getNode(event.recordId);
|
|
@@ -15794,7 +15797,7 @@ async function publishSubconsciousError(input) {
|
|
|
15794
15797
|
await input.sendStateSignal({
|
|
15795
15798
|
id: SUBCONSCIOUS_ACTIVITY_STATE_ID,
|
|
15796
15799
|
mode: "snapshot",
|
|
15797
|
-
cacheKey:
|
|
15800
|
+
cacheKey: await hashContents(contents),
|
|
15798
15801
|
tagName: "state",
|
|
15799
15802
|
attributes: { id: SUBCONSCIOUS_ACTIVITY_STATE_ID },
|
|
15800
15803
|
metadata: { origin: "subconscious" },
|
|
@@ -15806,7 +15809,7 @@ async function publishSubconsciousActivity(input) {
|
|
|
15806
15809
|
if (!input.sendStateSignal) return void 0;
|
|
15807
15810
|
const snapshot = await buildSubconsciousActivitySnapshot(input);
|
|
15808
15811
|
const contents = renderSubconsciousActivity(snapshot);
|
|
15809
|
-
const cacheKey =
|
|
15812
|
+
const cacheKey = await hashContents(contents);
|
|
15810
15813
|
await input.sendStateSignal({
|
|
15811
15814
|
id: SUBCONSCIOUS_ACTIVITY_STATE_ID,
|
|
15812
15815
|
mode: "snapshot",
|
|
@@ -17541,7 +17544,7 @@ function createAskMemoryTool(options) {
|
|
|
17541
17544
|
status: "rejected",
|
|
17542
17545
|
error: `ask_memory could not resolve calling agent ${parentAgentId} from the registered runtime.`
|
|
17543
17546
|
};
|
|
17544
|
-
const replyId = `subconscious:remind:${crypto
|
|
17547
|
+
const replyId = `subconscious:remind:${crypto.randomUUID()}:reply`;
|
|
17545
17548
|
try {
|
|
17546
17549
|
const scope = resolveKnowledgeToolScope(context);
|
|
17547
17550
|
const model = await resolveSubconsciousAgentModel({
|
|
@@ -17678,7 +17681,7 @@ function createReplyToMemoryQuestionTool(options) {
|
|
|
17678
17681
|
reason: "already-terminal"
|
|
17679
17682
|
};
|
|
17680
17683
|
const trimmedAnswer = answer.trim();
|
|
17681
|
-
const signalId = `${replyId}:${moreComing ? `partial:${crypto
|
|
17684
|
+
const signalId = `${replyId}:${moreComing ? `partial:${Buffer.from(await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(trimmedAnswer))).toString("hex").slice(0, 12)}` : "terminal"}:signal`;
|
|
17682
17685
|
if (deliveredSignalIds.has(signalId)) return {
|
|
17683
17686
|
delivered: true,
|
|
17684
17687
|
replyId,
|
|
@@ -21344,7 +21347,7 @@ function optimizeObservationsForContext(observations) {
|
|
|
21344
21347
|
//#region src/processors/observational-memory/temporary-memory.ts
|
|
21345
21348
|
function createTemporaryOmMemoryContext(prefix) {
|
|
21346
21349
|
const options = {
|
|
21347
|
-
thread: `${prefix}-${
|
|
21350
|
+
thread: `${prefix}-${globalThis.crypto.randomUUID()}`,
|
|
21348
21351
|
resource: prefix,
|
|
21349
21352
|
options: {
|
|
21350
21353
|
lastMessages: 10,
|
|
@@ -22197,6 +22200,10 @@ function isLikelyBase64Content(value) {
|
|
|
22197
22200
|
if (value.length < 16 || value.length % 4 !== 0 || /\s/.test(value) || isLikelyFilesystemPath(value)) return false;
|
|
22198
22201
|
return /^[A-Za-z0-9+/]+={0,2}$/.test(value);
|
|
22199
22202
|
}
|
|
22203
|
+
/**
|
|
22204
|
+
* Decodes a stored attachment payload (data URI, raw base64, Buffer, or typed array) into bytes.
|
|
22205
|
+
* Returns undefined for remote URLs, filesystem paths, and anything that isn't a decodable payload.
|
|
22206
|
+
*/
|
|
22200
22207
|
function decodeImageBuffer(value) {
|
|
22201
22208
|
if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) return value;
|
|
22202
22209
|
if (value instanceof Uint8Array) return Buffer.from(value);
|
|
@@ -24066,6 +24073,145 @@ function makePart(msg, partIndex, type, fullText, detail, toolName) {
|
|
|
24066
24073
|
toolName
|
|
24067
24074
|
};
|
|
24068
24075
|
}
|
|
24076
|
+
const PROVIDER_FILE_ID_PATTERN = /^file-[A-Za-z0-9_-]+$/;
|
|
24077
|
+
const REUSABLE_URL_PATTERN = /^[a-z][a-z0-9+.-]*:\/\/\S+$/i;
|
|
24078
|
+
const DATA_URI_PATTERN = /^data:([^;,]*)/i;
|
|
24079
|
+
const INLINE_DATA_OMITTED = "(inline data omitted)";
|
|
24080
|
+
/**
|
|
24081
|
+
* Reads the payload and media type of a stored image/file part. Stored parts use the v4
|
|
24082
|
+
* (`data`/`mimeType`) or v5 (`url`/`mediaType`) shape; prompt-style image parts carry the
|
|
24083
|
+
* payload in `image`. A data URI's header supplies the media type when none was stored.
|
|
24084
|
+
*/
|
|
24085
|
+
function readAttachmentPayload(part) {
|
|
24086
|
+
const payload = part.image ?? part.data ?? part.url;
|
|
24087
|
+
const payloadString = payload instanceof URL ? payload.href : typeof payload === "string" ? payload.trim() : "";
|
|
24088
|
+
const dataUriMatch = DATA_URI_PATTERN.exec(payloadString);
|
|
24089
|
+
const mediaType = [
|
|
24090
|
+
part.mimeType,
|
|
24091
|
+
part.mediaType,
|
|
24092
|
+
dataUriMatch?.[1]
|
|
24093
|
+
].find((v) => typeof v === "string" && v.length > 0);
|
|
24094
|
+
const hasBytes = payload instanceof Uint8Array || payload instanceof ArrayBuffer;
|
|
24095
|
+
return {
|
|
24096
|
+
payload,
|
|
24097
|
+
payloadString,
|
|
24098
|
+
isDataUri: dataUriMatch !== null,
|
|
24099
|
+
hasBytes,
|
|
24100
|
+
mediaType
|
|
24101
|
+
};
|
|
24102
|
+
}
|
|
24103
|
+
/** Returns the reference text for a payload the agent can reuse, or undefined for inline data. */
|
|
24104
|
+
function describeReusableReference(payloadString) {
|
|
24105
|
+
if (PROVIDER_FILE_ID_PATTERN.test(payloadString)) return `file id: ${payloadString}`;
|
|
24106
|
+
if (REUSABLE_URL_PATTERN.test(payloadString)) return `url: ${payloadString}`;
|
|
24107
|
+
}
|
|
24108
|
+
/**
|
|
24109
|
+
* Renders an image/file part with its media type and, when the stored payload is a reusable
|
|
24110
|
+
* reference (URL or provider file ID), that reference so the agent can reuse the attachment.
|
|
24111
|
+
* Inline payloads (data URIs, base64, bytes) are never rendered.
|
|
24112
|
+
*/
|
|
24113
|
+
function formatAttachmentPart(partType, part) {
|
|
24114
|
+
const filename = typeof part.filename === "string" && part.filename ? `: ${part.filename}` : "";
|
|
24115
|
+
const { payloadString, isDataUri, hasBytes, mediaType } = readAttachmentPayload(part);
|
|
24116
|
+
let reference = "";
|
|
24117
|
+
if (!isDataUri && payloadString) reference = describeReusableReference(payloadString) ?? INLINE_DATA_OMITTED;
|
|
24118
|
+
else if (isDataUri || hasBytes) reference = INLINE_DATA_OMITTED;
|
|
24119
|
+
return [
|
|
24120
|
+
`[${partType === "image" ? "Image" : "File"}${filename}]`,
|
|
24121
|
+
mediaType,
|
|
24122
|
+
reference
|
|
24123
|
+
].filter(Boolean).join(" ");
|
|
24124
|
+
}
|
|
24125
|
+
const INLINE_MEDIA_PART_TYPES = /* @__PURE__ */ new Set([
|
|
24126
|
+
"media",
|
|
24127
|
+
"image-data",
|
|
24128
|
+
"file-data",
|
|
24129
|
+
"image",
|
|
24130
|
+
"file"
|
|
24131
|
+
]);
|
|
24132
|
+
/**
|
|
24133
|
+
* Replaces inline media payloads nested in a stored tool result (for example a `media` part in
|
|
24134
|
+
* `modelOutput`, or a viewed attachment) with a placeholder, so rendering the result as text never
|
|
24135
|
+
* dumps base64. URLs and provider file IDs are kept because the agent can reuse them.
|
|
24136
|
+
*/
|
|
24137
|
+
function omitInlineMediaPayloads(value, seen = /* @__PURE__ */ new WeakMap()) {
|
|
24138
|
+
if (typeof value !== "object" || value === null) return value;
|
|
24139
|
+
if (seen.has(value)) return seen.get(value);
|
|
24140
|
+
if (Array.isArray(value)) {
|
|
24141
|
+
const items = [];
|
|
24142
|
+
seen.set(value, items);
|
|
24143
|
+
for (const item of value) items.push(omitInlineMediaPayloads(item, seen));
|
|
24144
|
+
return items;
|
|
24145
|
+
}
|
|
24146
|
+
const record = value;
|
|
24147
|
+
const isMediaPart = typeof record.type === "string" && INLINE_MEDIA_PART_TYPES.has(record.type);
|
|
24148
|
+
const result = {};
|
|
24149
|
+
seen.set(value, result);
|
|
24150
|
+
for (const [key, entry] of Object.entries(record)) if (isMediaPart && (key === "data" || key === "image") && typeof entry === "string" && !describeReusableReference(entry.trim())) result[key] = INLINE_DATA_OMITTED;
|
|
24151
|
+
else result[key] = omitInlineMediaPayloads(entry, seen);
|
|
24152
|
+
return result;
|
|
24153
|
+
}
|
|
24154
|
+
/**
|
|
24155
|
+
* Media types the model can be handed directly. Mirrors the observational memory observer's
|
|
24156
|
+
* default `observeAttachments` allowlist — anything else (docx, pptx, video, …) is not a type
|
|
24157
|
+
* providers accept as an inline part, so it stays text-only.
|
|
24158
|
+
*/
|
|
24159
|
+
function isViewableAttachmentMediaType(mediaType) {
|
|
24160
|
+
if (!mediaType) return false;
|
|
24161
|
+
const normalized = mediaType.toLowerCase();
|
|
24162
|
+
return normalized.startsWith("image/") || normalized === "application/pdf";
|
|
24163
|
+
}
|
|
24164
|
+
/** Mirrors core's DEFAULT_MAX_MEDIA_BYTES cap on inline media results. */
|
|
24165
|
+
const MAX_VIEWABLE_ATTACHMENT_BYTES = 10 * 1024 * 1024;
|
|
24166
|
+
function isRecallAttachmentContent(value) {
|
|
24167
|
+
if (typeof value !== "object" || value === null) return false;
|
|
24168
|
+
const content = value.content;
|
|
24169
|
+
if (!Array.isArray(content) || content.length !== 2) return false;
|
|
24170
|
+
return content.every((part) => {
|
|
24171
|
+
if (typeof part !== "object" || part === null) return false;
|
|
24172
|
+
const { type, text, data, mimeType } = part;
|
|
24173
|
+
if (type === "text") return typeof text === "string";
|
|
24174
|
+
return (type === "image" || type === "file") && typeof data === "string" && typeof mimeType === "string";
|
|
24175
|
+
});
|
|
24176
|
+
}
|
|
24177
|
+
/**
|
|
24178
|
+
* Turns an attachment part into a model-viewable payload. Only inline payloads are returned, as
|
|
24179
|
+
* base64 bytes. Everything else — remote URLs, provider file IDs, oversized payloads, unsupported
|
|
24180
|
+
* media types — comes back as an explanation for the agent instead.
|
|
24181
|
+
*/
|
|
24182
|
+
function resolveViewableAttachment(part) {
|
|
24183
|
+
const { payload, payloadString, isDataUri, hasBytes, mediaType } = readAttachmentPayload(part);
|
|
24184
|
+
if (!payloadString && !hasBytes) return { note: "This attachment has no stored payload to show." };
|
|
24185
|
+
if (!isViewableAttachmentMediaType(mediaType)) return { note: mediaType ? `Attachments of type ${mediaType} can't be shown inline. Use the attachment's url or file id if you need to reference it.` : "This attachment has no media type recorded, so it can't be shown inline." };
|
|
24186
|
+
if (isHttpUrlString(payloadString)) return { note: "This attachment is stored at a remote URL, so it can't be shown inline. Use its url if you need to reference it." };
|
|
24187
|
+
if (payloadString.length * .75 > MAX_VIEWABLE_ATTACHMENT_BYTES) return { note: "This attachment is too large to show inline." };
|
|
24188
|
+
const bytes = decodeImageBuffer(isDataUri ? `data:${payloadString.slice(5)}` : payloadString || payload);
|
|
24189
|
+
if (!bytes) return { note: "This attachment's payload is not inline data, so it can't be shown." };
|
|
24190
|
+
if (bytes.byteLength > MAX_VIEWABLE_ATTACHMENT_BYTES) return { note: "This attachment is too large to show inline." };
|
|
24191
|
+
return {
|
|
24192
|
+
data: bytes.toString("base64"),
|
|
24193
|
+
mimeType: mediaType
|
|
24194
|
+
};
|
|
24195
|
+
}
|
|
24196
|
+
/**
|
|
24197
|
+
* Presents a resolved attachment to the model as a native base64 `media` part alongside its text
|
|
24198
|
+
* description.
|
|
24199
|
+
*/
|
|
24200
|
+
function recallAttachmentToModelOutput(output) {
|
|
24201
|
+
if (!isRecallAttachmentContent(output)) return void 0;
|
|
24202
|
+
const [textPart, attachment] = output.content;
|
|
24203
|
+
return {
|
|
24204
|
+
type: "content",
|
|
24205
|
+
value: [{
|
|
24206
|
+
type: "text",
|
|
24207
|
+
text: textPart.text
|
|
24208
|
+
}, {
|
|
24209
|
+
type: "media",
|
|
24210
|
+
data: attachment.data,
|
|
24211
|
+
mediaType: attachment.mimeType
|
|
24212
|
+
}]
|
|
24213
|
+
};
|
|
24214
|
+
}
|
|
24069
24215
|
function formatMessageParts(msg, detail) {
|
|
24070
24216
|
const parts = [];
|
|
24071
24217
|
if (typeof msg.content === "string") {
|
|
@@ -24098,7 +24244,7 @@ function formatMessageParts(msg, detail) {
|
|
|
24098
24244
|
}
|
|
24099
24245
|
if (inv.state === "result") {
|
|
24100
24246
|
const { value: resultValue } = resolveToolResultValue(part, inv.result);
|
|
24101
|
-
const resultStr = formatToolResultForObserver(resultValue, { maxTokens: HIGH_DETAIL_TOOL_RESULT_TOKENS });
|
|
24247
|
+
const resultStr = formatToolResultForObserver(omitInlineMediaPayloads(resultValue), { maxTokens: HIGH_DETAIL_TOOL_RESULT_TOKENS });
|
|
24102
24248
|
const fullText = `[Tool Result: ${inv.toolName}]\n${resultStr}`;
|
|
24103
24249
|
parts.push(makePart(msg, i, "tool-result", fullText, detail, inv.toolName));
|
|
24104
24250
|
}
|
|
@@ -24121,25 +24267,14 @@ function formatMessageParts(msg, detail) {
|
|
|
24121
24267
|
} else if (partType === "tool-result") {
|
|
24122
24268
|
const toolName = part.toolName;
|
|
24123
24269
|
if (toolName) {
|
|
24124
|
-
const fullText = `[Tool Result: ${toolName}]\n${formatToolResultForObserver(part.output ?? part.result, { maxTokens: HIGH_DETAIL_TOOL_RESULT_TOKENS })}`;
|
|
24270
|
+
const fullText = `[Tool Result: ${toolName}]\n${formatToolResultForObserver(omitInlineMediaPayloads(part.output ?? part.result), { maxTokens: HIGH_DETAIL_TOOL_RESULT_TOKENS })}`;
|
|
24125
24271
|
parts.push(makePart(msg, i, "tool-result", fullText, detail, toolName));
|
|
24126
24272
|
}
|
|
24127
24273
|
} else if (partType === "reasoning") {
|
|
24128
24274
|
const reasoning = part.reasoning ?? part.text;
|
|
24129
24275
|
if (reasoning) parts.push(makePart(msg, i, "reasoning", reasoning, detail));
|
|
24130
|
-
} else if (partType === "image" || partType === "file")
|
|
24131
|
-
|
|
24132
|
-
const label = filename ? `: ${filename}` : "";
|
|
24133
|
-
const fullText = `[${partType === "image" ? "Image" : "File"}${label}]`;
|
|
24134
|
-
parts.push({
|
|
24135
|
-
messageId: msg.id,
|
|
24136
|
-
partIndex: i,
|
|
24137
|
-
role: msg.role,
|
|
24138
|
-
type: partType,
|
|
24139
|
-
text: fullText,
|
|
24140
|
-
fullText
|
|
24141
|
-
});
|
|
24142
|
-
} else if (partType?.startsWith("data-")) {} else if (partType) {
|
|
24276
|
+
} else if (partType === "image" || partType === "file") parts.push(makePart(msg, i, partType, formatAttachmentPart(partType, part), detail));
|
|
24277
|
+
else if (partType?.startsWith("data-")) {} else if (partType) {
|
|
24143
24278
|
const fullText = `[${partType}]`;
|
|
24144
24279
|
parts.push({
|
|
24145
24280
|
messageId: msg.id,
|
|
@@ -24312,6 +24447,29 @@ async function recallPart({ memory, threadId, resourceId, cursor, partIndex, cha
|
|
|
24312
24447
|
note
|
|
24313
24448
|
};
|
|
24314
24449
|
}
|
|
24450
|
+
async function recallAttachmentView({ memory, threadId, resourceId, cursor, partIndex, threadScope, retrievalScope = "thread" }) {
|
|
24451
|
+
if (!memory || typeof memory.getMemoryStore !== "function") throw new Error("Memory instance is required for recall");
|
|
24452
|
+
if (!threadId) throw new Error("Thread ID is required for recall");
|
|
24453
|
+
const resolved = await resolveCursorMessage(memory, cursor, {
|
|
24454
|
+
resourceId,
|
|
24455
|
+
threadScope,
|
|
24456
|
+
enforceThreadScope: retrievalScope !== "resource"
|
|
24457
|
+
});
|
|
24458
|
+
if ("hint" in resolved) return { messages: resolved.hint };
|
|
24459
|
+
const rawPart = getMessageParts(resolved)[partIndex];
|
|
24460
|
+
const partType = rawPart?.type;
|
|
24461
|
+
if (!rawPart || partType !== "image" && partType !== "file") return { messages: `Part ${partIndex} of message ${cursor} is ${rawPart ? `a ${partType ?? "unknown"}-type part` : "missing"}, not an attachment. Call recall with the same cursor and partIndex without viewAttachment to read it.` };
|
|
24462
|
+
const resolvedAttachment = resolveViewableAttachment(rawPart);
|
|
24463
|
+
if ("note" in resolvedAttachment) return { messages: `${formatAttachmentPart(partType, rawPart)} — ${resolvedAttachment.note}` };
|
|
24464
|
+
return { content: [{
|
|
24465
|
+
type: "text",
|
|
24466
|
+
text: formatAttachmentPart(partType, rawPart)
|
|
24467
|
+
}, {
|
|
24468
|
+
type: partType === "image" ? "image" : "file",
|
|
24469
|
+
data: resolvedAttachment.data,
|
|
24470
|
+
mimeType: resolvedAttachment.mimeType
|
|
24471
|
+
}] };
|
|
24472
|
+
}
|
|
24315
24473
|
async function recallMessages({ memory, threadId, resourceId, cursor, page = 1, limit = 20, detail = "low", partType, toolName, threadScope, retrievalScope = "thread", maxTokens = DEFAULT_MAX_RESULT_TOKENS }) {
|
|
24316
24474
|
if (!memory) throw new Error("Memory instance is required for recall");
|
|
24317
24475
|
if (!threadId) throw new Error("Thread ID is required for recall");
|
|
@@ -24597,11 +24755,15 @@ const recallTool = (_memoryConfig, options) => {
|
|
|
24597
24755
|
type: "integer",
|
|
24598
24756
|
minimum: 0,
|
|
24599
24757
|
description: "Continue reading a truncated single part from this position. Pass the exact nextCharOffset value returned by a previous call; do not compute it yourself. Only applies with cursor and partIndex in mode=\"messages\"."
|
|
24758
|
+
},
|
|
24759
|
+
viewAttachment: {
|
|
24760
|
+
type: "boolean",
|
|
24761
|
+
description: "Show the actual attachment instead of just describing it. Requires cursor and partIndex, and only applies when that part is an image or file. Use it after recall shows you an attachment you need to look at."
|
|
24600
24762
|
}
|
|
24601
24763
|
}
|
|
24602
24764
|
},
|
|
24603
24765
|
execute: async (inputData, context) => {
|
|
24604
|
-
const { mode, query, cursor, threadId: explicitThreadId, anchor, page, limit, detail, partType, toolName, partIndex, charOffset, before, after } = inputData;
|
|
24766
|
+
const { mode, query, cursor, threadId: explicitThreadId, anchor, page, limit, detail, partType, toolName, partIndex, charOffset, before, after, viewAttachment } = inputData;
|
|
24605
24767
|
const memory = context?.memory;
|
|
24606
24768
|
const currentThreadId = context?.agent?.threadId;
|
|
24607
24769
|
const resourceId = context?.agent?.resourceId;
|
|
@@ -24690,6 +24852,7 @@ const recallTool = (_memoryConfig, options) => {
|
|
|
24690
24852
|
targetThreadId = resolved.threadId;
|
|
24691
24853
|
}
|
|
24692
24854
|
if (!targetThreadId) throw new Error("Thread ID is required for recall");
|
|
24855
|
+
if (viewAttachment && (!cursor || partIndex === void 0 || partIndex === null)) return { messages: "viewAttachment needs both cursor and partIndex so it knows which attachment to show. Call recall with cursor, partIndex, and viewAttachment: true." };
|
|
24693
24856
|
if (!cursor) {
|
|
24694
24857
|
const result = await recallThreadFromStart({
|
|
24695
24858
|
memory,
|
|
@@ -24708,16 +24871,27 @@ const recallTool = (_memoryConfig, options) => {
|
|
|
24708
24871
|
};
|
|
24709
24872
|
return result;
|
|
24710
24873
|
}
|
|
24711
|
-
if (partIndex !== void 0 && partIndex !== null)
|
|
24712
|
-
|
|
24713
|
-
|
|
24714
|
-
|
|
24715
|
-
|
|
24716
|
-
|
|
24717
|
-
|
|
24718
|
-
|
|
24719
|
-
|
|
24720
|
-
|
|
24874
|
+
if (partIndex !== void 0 && partIndex !== null) {
|
|
24875
|
+
if (viewAttachment) return recallAttachmentView({
|
|
24876
|
+
memory,
|
|
24877
|
+
threadId: targetThreadId,
|
|
24878
|
+
resourceId,
|
|
24879
|
+
cursor,
|
|
24880
|
+
partIndex,
|
|
24881
|
+
threadScope,
|
|
24882
|
+
retrievalScope
|
|
24883
|
+
});
|
|
24884
|
+
return recallPart({
|
|
24885
|
+
memory,
|
|
24886
|
+
threadId: targetThreadId,
|
|
24887
|
+
resourceId,
|
|
24888
|
+
cursor,
|
|
24889
|
+
partIndex,
|
|
24890
|
+
charOffset,
|
|
24891
|
+
threadScope,
|
|
24892
|
+
retrievalScope
|
|
24893
|
+
});
|
|
24894
|
+
}
|
|
24721
24895
|
return recallMessages({
|
|
24722
24896
|
memory,
|
|
24723
24897
|
threadId: targetThreadId,
|
|
@@ -24731,7 +24905,8 @@ const recallTool = (_memoryConfig, options) => {
|
|
|
24731
24905
|
threadScope,
|
|
24732
24906
|
retrievalScope
|
|
24733
24907
|
});
|
|
24734
|
-
}
|
|
24908
|
+
},
|
|
24909
|
+
toModelOutput: recallAttachmentToModelOutput
|
|
24735
24910
|
});
|
|
24736
24911
|
};
|
|
24737
24912
|
//#endregion
|
|
@@ -25692,7 +25867,7 @@ function stripReflectionGroupMetadata(body) {
|
|
|
25692
25867
|
return body.replace(/^_range:\s*`[^`]*`_\s*\n?/m, "").trim();
|
|
25693
25868
|
}
|
|
25694
25869
|
function generateAnchorId() {
|
|
25695
|
-
return (
|
|
25870
|
+
return Buffer.from(globalThis.crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(8))).toString("hex");
|
|
25696
25871
|
}
|
|
25697
25872
|
function wrapInObservationGroup(observations, range, id = generateAnchorId(), _sourceGroupIds, kind) {
|
|
25698
25873
|
const content = observations.trim();
|
|
@@ -29044,7 +29219,7 @@ function inferReproIdRemap(preMessages, postMessages) {
|
|
|
29044
29219
|
}
|
|
29045
29220
|
function createOmReproCaptureDir(threadId, label) {
|
|
29046
29221
|
const sanitizedThreadId = sanitizeCapturePathSegment(threadId);
|
|
29047
|
-
const captureDir = (0, path.join)(process.cwd(), getOmReproCaptureDir(), sanitizedThreadId, `${Date.now()}-${label}-${
|
|
29222
|
+
const captureDir = (0, path.join)(process.cwd(), getOmReproCaptureDir(), sanitizedThreadId, `${Date.now()}-${label}-${globalThis.crypto.randomUUID()}`);
|
|
29048
29223
|
(0, fs.mkdirSync)(captureDir, { recursive: true });
|
|
29049
29224
|
return captureDir;
|
|
29050
29225
|
}
|
|
@@ -33596,18 +33771,19 @@ Notes:
|
|
|
33596
33771
|
const embedResult = await this.embedMessageContent(text);
|
|
33597
33772
|
if (embedResult.embeddings.length === 0 || embedResult.dimension === void 0) return;
|
|
33598
33773
|
const { indexName } = await this.createObservationEmbeddingIndex(embedResult.dimension);
|
|
33599
|
-
const ids =
|
|
33600
|
-
|
|
33774
|
+
const ids = [];
|
|
33775
|
+
for (const [chunkIndex] of embedResult.chunks.entries()) {
|
|
33776
|
+
const hash = Buffer.from(await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(JSON.stringify([
|
|
33601
33777
|
resourceId,
|
|
33602
33778
|
threadId,
|
|
33603
33779
|
groupId,
|
|
33604
33780
|
chunkIndex
|
|
33605
|
-
]))
|
|
33781
|
+
]))));
|
|
33606
33782
|
hash[6] = hash[6] & 15 | 128;
|
|
33607
33783
|
hash[8] = hash[8] & 63 | 128;
|
|
33608
33784
|
const hex = hash.toString("hex", 0, 16);
|
|
33609
|
-
|
|
33610
|
-
}
|
|
33785
|
+
ids.push(`${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`);
|
|
33786
|
+
}
|
|
33611
33787
|
await this.vector.upsert({
|
|
33612
33788
|
indexName,
|
|
33613
33789
|
ids,
|
|
@@ -34774,4 +34950,4 @@ Object.defineProperty(exports, "wrapInObservationGroup", {
|
|
|
34774
34950
|
}
|
|
34775
34951
|
});
|
|
34776
34952
|
|
|
34777
|
-
//# sourceMappingURL=src-
|
|
34953
|
+
//# sourceMappingURL=src-Cm4sUXMu.cjs.map
|