@mastra/server 1.72.0 → 1.73.0-alpha.0

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.
Files changed (73) hide show
  1. package/dist/{a2a-D2BffGsK.js → a2a-Dyd6lbnr.js} +35 -23
  2. package/dist/a2a-Dyd6lbnr.js.map +1 -0
  3. package/dist/{a2a-CAQVpVxH.cjs → a2a-rSyYjbA3.cjs} +35 -24
  4. package/dist/a2a-rSyYjbA3.cjs.map +1 -0
  5. package/dist/{api-schema-manifest-CaZU5zVt.cjs → api-schema-manifest-azbFW2gh.cjs} +2 -2
  6. package/dist/{api-schema-manifest-CaZU5zVt.cjs.map → api-schema-manifest-azbFW2gh.cjs.map} +1 -1
  7. package/dist/{api-schema-manifest-wF1O8MCU.js → api-schema-manifest-btfn_x2G.js} +2 -2
  8. package/dist/{api-schema-manifest-wF1O8MCU.js.map → api-schema-manifest-btfn_x2G.js.map} +1 -1
  9. package/dist/{dist-CYk5xS3y.js → dist-B2EGPe0Y.js} +219 -42
  10. package/dist/dist-B2EGPe0Y.js.map +1 -0
  11. package/dist/{dist-CRMvLG_8.cjs → dist-BJfoL3Lt.cjs} +219 -43
  12. package/dist/dist-BJfoL3Lt.cjs.map +1 -0
  13. package/dist/docs/SKILL.md +2 -1
  14. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  15. package/dist/docs/references/docs-guides-mcp-authentication-authorization.md +136 -0
  16. package/dist/{processors-88oJ_4J-.js → processors-33IULT8X.js} +7 -4
  17. package/dist/processors-33IULT8X.js.map +1 -0
  18. package/dist/{processors-D6lRjS0e.cjs → processors-80HWq8nr.cjs} +7 -4
  19. package/dist/processors-80HWq8nr.cjs.map +1 -0
  20. package/dist/{routes-x4As7pym.cjs → routes-BaQVELB2.cjs} +2 -2
  21. package/dist/{routes-x4As7pym.cjs.map → routes-BaQVELB2.cjs.map} +1 -1
  22. package/dist/{routes-B6soWZap.js → routes-BqoNkLiT.js} +2 -2
  23. package/dist/{routes-B6soWZap.js.map → routes-BqoNkLiT.js.map} +1 -1
  24. package/dist/server/a2a/agent-card-signing.d.ts.map +1 -1
  25. package/dist/server/handlers/a2a.cjs +1 -1
  26. package/dist/server/handlers/a2a.js +1 -1
  27. package/dist/server/handlers/agent-builder.cjs +1 -1
  28. package/dist/server/handlers/agent-builder.js +1 -1
  29. package/dist/server/handlers/agents.cjs +2 -2
  30. package/dist/server/handlers/agents.cjs.map +1 -1
  31. package/dist/server/handlers/agents.d.ts.map +1 -1
  32. package/dist/server/handlers/agents.js +3 -3
  33. package/dist/server/handlers/agents.js.map +1 -1
  34. package/dist/server/handlers/conversations.cjs +1 -2
  35. package/dist/server/handlers/conversations.cjs.map +1 -1
  36. package/dist/server/handlers/conversations.d.ts.map +1 -1
  37. package/dist/server/handlers/conversations.js +1 -2
  38. package/dist/server/handlers/conversations.js.map +1 -1
  39. package/dist/server/handlers/processors.cjs +3 -1
  40. package/dist/server/handlers/processors.cjs.map +1 -1
  41. package/dist/server/handlers/processors.d.ts +6 -3
  42. package/dist/server/handlers/processors.d.ts.map +1 -1
  43. package/dist/server/handlers/processors.js +3 -1
  44. package/dist/server/handlers/processors.js.map +1 -1
  45. package/dist/server/handlers/responses.adapter.cjs +1 -2
  46. package/dist/server/handlers/responses.adapter.cjs.map +1 -1
  47. package/dist/server/handlers/responses.adapter.d.ts.map +1 -1
  48. package/dist/server/handlers/responses.adapter.js +1 -2
  49. package/dist/server/handlers/responses.adapter.js.map +1 -1
  50. package/dist/server/handlers/responses.cjs +1 -2
  51. package/dist/server/handlers/responses.cjs.map +1 -1
  52. package/dist/server/handlers/responses.d.ts.map +1 -1
  53. package/dist/server/handlers/responses.js +1 -2
  54. package/dist/server/handlers/responses.js.map +1 -1
  55. package/dist/server/handlers/system.cjs +1 -1
  56. package/dist/server/handlers/system.js +1 -1
  57. package/dist/server/handlers.cjs +1 -1
  58. package/dist/server/handlers.js +1 -1
  59. package/dist/server/schemas/index.cjs +1 -1
  60. package/dist/server/schemas/index.js +1 -1
  61. package/dist/server/schemas/processors.d.ts +4 -0
  62. package/dist/server/schemas/processors.d.ts.map +1 -1
  63. package/dist/server/server-adapter/index.cjs +1 -1
  64. package/dist/server/server-adapter/index.js +1 -1
  65. package/dist/server/server-adapter/routes/processors.d.ts +6 -3
  66. package/dist/server/server-adapter/routes/processors.d.ts.map +1 -1
  67. package/package.json +5 -5
  68. package/dist/a2a-CAQVpVxH.cjs.map +0 -1
  69. package/dist/a2a-D2BffGsK.js.map +0 -1
  70. package/dist/dist-CRMvLG_8.cjs.map +0 -1
  71. package/dist/dist-CYk5xS3y.js.map +0 -1
  72. package/dist/processors-88oJ_4J-.js.map +0 -1
  73. package/dist/processors-D6lRjS0e.cjs.map +0 -1
@@ -15,7 +15,6 @@ import { ErrorCategory, ErrorDomain, MastraError } from "@mastra/core/error";
15
15
  import { ModelRouterLanguageModel, modelSupportsAttachments, modelSupportsTemperature, resolveModelConfig } from "@mastra/core/llm";
16
16
  import { createTool } from "@mastra/core/tools";
17
17
  import { inspect, promisify } from "util";
18
- import crypto$1, { createHash, randomBytes, randomUUID } from "crypto";
19
18
  import { MASTRA_THREAD_ID_KEY, RequestContext } from "@mastra/core/request-context";
20
19
  import { generateEmptyFromSchema } from "@mastra/core/utils";
21
20
  import { InMemoryStore, MAX_KNOWLEDGE_NODE_DESCRIPTION_LENGTH, assertKnowledgeScopeWithinCeiling, canonicalizeKnowledgeScope, createKnowledgeNodeCursor, expandKnowledgeScope, isKnowledgeScopeVisible, knowledgeScopeKey } from "@mastra/core/storage";
@@ -26,6 +25,7 @@ import { createStep, createWorkflow } from "@mastra/core/workflows";
26
25
  import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
27
26
  import { tmpdir } from "os";
28
27
  import { basename, dirname, extname, isAbsolute, join, relative, resolve } from "path";
28
+ import { createHash } from "crypto";
29
29
  import { channel, tracingChannel } from "diagnostics_channel";
30
30
  import { AsyncLocalStorage } from "async_hooks";
31
31
  import { exec, execFile, spawn } from "child_process";
@@ -4637,7 +4637,7 @@ function splitLines(text) {
4637
4637
  return result;
4638
4638
  }
4639
4639
  //#endregion
4640
- //#region ../memory/dist/src-BdfOygyn.js
4640
+ //#region ../memory/dist/src-BYAwbfUo.js
4641
4641
  var __defProp$3 = Object.defineProperty;
4642
4642
  var __exportAll = (all, no_symbols) => {
4643
4643
  let target = {};
@@ -20235,6 +20235,10 @@ if (OM_DEBUG_LOG) {
20235
20235
  };
20236
20236
  }
20237
20237
  const SUBCONSCIOUS_ACTIVITY_STATE_ID = "subconscious-activity";
20238
+ async function hashContents(contents) {
20239
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(contents));
20240
+ return Buffer.from(digest).toString("hex");
20241
+ }
20238
20242
  async function getActivityTarget(store, event, scope) {
20239
20243
  if (event.recordType === "node") {
20240
20244
  const node = await store.getNode(event.recordId);
@@ -20336,7 +20340,7 @@ async function publishSubconsciousError(input) {
20336
20340
  await input.sendStateSignal({
20337
20341
  id: SUBCONSCIOUS_ACTIVITY_STATE_ID,
20338
20342
  mode: "snapshot",
20339
- cacheKey: createHash("sha256").update(contents).digest("hex"),
20343
+ cacheKey: await hashContents(contents),
20340
20344
  tagName: "state",
20341
20345
  attributes: { id: SUBCONSCIOUS_ACTIVITY_STATE_ID },
20342
20346
  metadata: { origin: "subconscious" },
@@ -20348,7 +20352,7 @@ async function publishSubconsciousActivity(input) {
20348
20352
  if (!input.sendStateSignal) return void 0;
20349
20353
  const snapshot = await buildSubconsciousActivitySnapshot(input);
20350
20354
  const contents = renderSubconsciousActivity(snapshot);
20351
- const cacheKey = createHash("sha256").update(contents).digest("hex");
20355
+ const cacheKey = await hashContents(contents);
20352
20356
  await input.sendStateSignal({
20353
20357
  id: SUBCONSCIOUS_ACTIVITY_STATE_ID,
20354
20358
  mode: "snapshot",
@@ -22059,7 +22063,7 @@ function createAskMemoryTool(options) {
22059
22063
  status: "rejected",
22060
22064
  error: `ask_memory could not resolve calling agent ${parentAgentId} from the registered runtime.`
22061
22065
  };
22062
- const replyId = `subconscious:remind:${crypto$1.randomUUID()}:reply`;
22066
+ const replyId = `subconscious:remind:${crypto.randomUUID()}:reply`;
22063
22067
  try {
22064
22068
  const scope = resolveKnowledgeToolScope(context);
22065
22069
  const model = await resolveSubconsciousAgentModel({
@@ -22196,7 +22200,7 @@ function createReplyToMemoryQuestionTool(options) {
22196
22200
  reason: "already-terminal"
22197
22201
  };
22198
22202
  const trimmedAnswer = answer.trim();
22199
- const signalId = `${replyId}:${moreComing ? `partial:${crypto$1.createHash("sha256").update(trimmedAnswer).digest("hex").slice(0, 12)}` : "terminal"}:signal`;
22203
+ 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`;
22200
22204
  if (deliveredSignalIds.has(signalId)) return {
22201
22205
  delivered: true,
22202
22206
  replyId,
@@ -25826,7 +25830,7 @@ function optimizeObservationsForContext(observations) {
25826
25830
  }
25827
25831
  function createTemporaryOmMemoryContext(prefix) {
25828
25832
  const options = {
25829
- thread: `${prefix}-${randomUUID()}`,
25833
+ thread: `${prefix}-${globalThis.crypto.randomUUID()}`,
25830
25834
  resource: prefix,
25831
25835
  options: {
25832
25836
  lastMessages: 10,
@@ -26669,6 +26673,10 @@ function isLikelyBase64Content(value) {
26669
26673
  if (value.length < 16 || value.length % 4 !== 0 || /\s/.test(value) || isLikelyFilesystemPath(value)) return false;
26670
26674
  return /^[A-Za-z0-9+/]+={0,2}$/.test(value);
26671
26675
  }
26676
+ /**
26677
+ * Decodes a stored attachment payload (data URI, raw base64, Buffer, or typed array) into bytes.
26678
+ * Returns undefined for remote URLs, filesystem paths, and anything that isn't a decodable payload.
26679
+ */
26672
26680
  function decodeImageBuffer(value) {
26673
26681
  if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) return value;
26674
26682
  if (value instanceof Uint8Array) return Buffer.from(value);
@@ -28530,6 +28538,145 @@ function makePart(msg, partIndex, type, fullText, detail, toolName) {
28530
28538
  toolName
28531
28539
  };
28532
28540
  }
28541
+ const PROVIDER_FILE_ID_PATTERN = /^file-[A-Za-z0-9_-]+$/;
28542
+ const REUSABLE_URL_PATTERN = /^[a-z][a-z0-9+.-]*:\/\/\S+$/i;
28543
+ const DATA_URI_PATTERN = /^data:([^;,]*)/i;
28544
+ const INLINE_DATA_OMITTED = "(inline data omitted)";
28545
+ /**
28546
+ * Reads the payload and media type of a stored image/file part. Stored parts use the v4
28547
+ * (`data`/`mimeType`) or v5 (`url`/`mediaType`) shape; prompt-style image parts carry the
28548
+ * payload in `image`. A data URI's header supplies the media type when none was stored.
28549
+ */
28550
+ function readAttachmentPayload(part) {
28551
+ const payload = part.image ?? part.data ?? part.url;
28552
+ const payloadString = payload instanceof URL ? payload.href : typeof payload === "string" ? payload.trim() : "";
28553
+ const dataUriMatch = DATA_URI_PATTERN.exec(payloadString);
28554
+ const mediaType = [
28555
+ part.mimeType,
28556
+ part.mediaType,
28557
+ dataUriMatch?.[1]
28558
+ ].find((v) => typeof v === "string" && v.length > 0);
28559
+ const hasBytes = payload instanceof Uint8Array || payload instanceof ArrayBuffer;
28560
+ return {
28561
+ payload,
28562
+ payloadString,
28563
+ isDataUri: dataUriMatch !== null,
28564
+ hasBytes,
28565
+ mediaType
28566
+ };
28567
+ }
28568
+ /** Returns the reference text for a payload the agent can reuse, or undefined for inline data. */
28569
+ function describeReusableReference(payloadString) {
28570
+ if (PROVIDER_FILE_ID_PATTERN.test(payloadString)) return `file id: ${payloadString}`;
28571
+ if (REUSABLE_URL_PATTERN.test(payloadString)) return `url: ${payloadString}`;
28572
+ }
28573
+ /**
28574
+ * Renders an image/file part with its media type and, when the stored payload is a reusable
28575
+ * reference (URL or provider file ID), that reference so the agent can reuse the attachment.
28576
+ * Inline payloads (data URIs, base64, bytes) are never rendered.
28577
+ */
28578
+ function formatAttachmentPart(partType, part) {
28579
+ const filename = typeof part.filename === "string" && part.filename ? `: ${part.filename}` : "";
28580
+ const { payloadString, isDataUri, hasBytes, mediaType } = readAttachmentPayload(part);
28581
+ let reference = "";
28582
+ if (!isDataUri && payloadString) reference = describeReusableReference(payloadString) ?? INLINE_DATA_OMITTED;
28583
+ else if (isDataUri || hasBytes) reference = INLINE_DATA_OMITTED;
28584
+ return [
28585
+ `[${partType === "image" ? "Image" : "File"}${filename}]`,
28586
+ mediaType,
28587
+ reference
28588
+ ].filter(Boolean).join(" ");
28589
+ }
28590
+ const INLINE_MEDIA_PART_TYPES = /* @__PURE__ */ new Set([
28591
+ "media",
28592
+ "image-data",
28593
+ "file-data",
28594
+ "image",
28595
+ "file"
28596
+ ]);
28597
+ /**
28598
+ * Replaces inline media payloads nested in a stored tool result (for example a `media` part in
28599
+ * `modelOutput`, or a viewed attachment) with a placeholder, so rendering the result as text never
28600
+ * dumps base64. URLs and provider file IDs are kept because the agent can reuse them.
28601
+ */
28602
+ function omitInlineMediaPayloads(value, seen = /* @__PURE__ */ new WeakMap()) {
28603
+ if (typeof value !== "object" || value === null) return value;
28604
+ if (seen.has(value)) return seen.get(value);
28605
+ if (Array.isArray(value)) {
28606
+ const items = [];
28607
+ seen.set(value, items);
28608
+ for (const item of value) items.push(omitInlineMediaPayloads(item, seen));
28609
+ return items;
28610
+ }
28611
+ const record = value;
28612
+ const isMediaPart = typeof record.type === "string" && INLINE_MEDIA_PART_TYPES.has(record.type);
28613
+ const result = {};
28614
+ seen.set(value, result);
28615
+ 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;
28616
+ else result[key] = omitInlineMediaPayloads(entry, seen);
28617
+ return result;
28618
+ }
28619
+ /**
28620
+ * Media types the model can be handed directly. Mirrors the observational memory observer's
28621
+ * default `observeAttachments` allowlist — anything else (docx, pptx, video, …) is not a type
28622
+ * providers accept as an inline part, so it stays text-only.
28623
+ */
28624
+ function isViewableAttachmentMediaType(mediaType) {
28625
+ if (!mediaType) return false;
28626
+ const normalized = mediaType.toLowerCase();
28627
+ return normalized.startsWith("image/") || normalized === "application/pdf";
28628
+ }
28629
+ /** Mirrors core's DEFAULT_MAX_MEDIA_BYTES cap on inline media results. */
28630
+ const MAX_VIEWABLE_ATTACHMENT_BYTES = 10 * 1024 * 1024;
28631
+ function isRecallAttachmentContent(value) {
28632
+ if (typeof value !== "object" || value === null) return false;
28633
+ const content = value.content;
28634
+ if (!Array.isArray(content) || content.length !== 2) return false;
28635
+ return content.every((part) => {
28636
+ if (typeof part !== "object" || part === null) return false;
28637
+ const { type, text, data, mimeType } = part;
28638
+ if (type === "text") return typeof text === "string";
28639
+ return (type === "image" || type === "file") && typeof data === "string" && typeof mimeType === "string";
28640
+ });
28641
+ }
28642
+ /**
28643
+ * Turns an attachment part into a model-viewable payload. Only inline payloads are returned, as
28644
+ * base64 bytes. Everything else — remote URLs, provider file IDs, oversized payloads, unsupported
28645
+ * media types — comes back as an explanation for the agent instead.
28646
+ */
28647
+ function resolveViewableAttachment(part) {
28648
+ const { payload, payloadString, isDataUri, hasBytes, mediaType } = readAttachmentPayload(part);
28649
+ if (!payloadString && !hasBytes) return { note: "This attachment has no stored payload to show." };
28650
+ 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." };
28651
+ 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." };
28652
+ if (payloadString.length * .75 > MAX_VIEWABLE_ATTACHMENT_BYTES) return { note: "This attachment is too large to show inline." };
28653
+ const bytes = decodeImageBuffer(isDataUri ? `data:${payloadString.slice(5)}` : payloadString || payload);
28654
+ if (!bytes) return { note: "This attachment's payload is not inline data, so it can't be shown." };
28655
+ if (bytes.byteLength > MAX_VIEWABLE_ATTACHMENT_BYTES) return { note: "This attachment is too large to show inline." };
28656
+ return {
28657
+ data: bytes.toString("base64"),
28658
+ mimeType: mediaType
28659
+ };
28660
+ }
28661
+ /**
28662
+ * Presents a resolved attachment to the model as a native base64 `media` part alongside its text
28663
+ * description.
28664
+ */
28665
+ function recallAttachmentToModelOutput(output) {
28666
+ if (!isRecallAttachmentContent(output)) return void 0;
28667
+ const [textPart, attachment] = output.content;
28668
+ return {
28669
+ type: "content",
28670
+ value: [{
28671
+ type: "text",
28672
+ text: textPart.text
28673
+ }, {
28674
+ type: "media",
28675
+ data: attachment.data,
28676
+ mediaType: attachment.mimeType
28677
+ }]
28678
+ };
28679
+ }
28533
28680
  function formatMessageParts(msg, detail) {
28534
28681
  const parts = [];
28535
28682
  if (typeof msg.content === "string") {
@@ -28562,7 +28709,7 @@ function formatMessageParts(msg, detail) {
28562
28709
  }
28563
28710
  if (inv.state === "result") {
28564
28711
  const { value: resultValue } = resolveToolResultValue(part, inv.result);
28565
- const resultStr = formatToolResultForObserver(resultValue, { maxTokens: HIGH_DETAIL_TOOL_RESULT_TOKENS });
28712
+ const resultStr = formatToolResultForObserver(omitInlineMediaPayloads(resultValue), { maxTokens: HIGH_DETAIL_TOOL_RESULT_TOKENS });
28566
28713
  const fullText = `[Tool Result: ${inv.toolName}]\n${resultStr}`;
28567
28714
  parts.push(makePart(msg, i, "tool-result", fullText, detail, inv.toolName));
28568
28715
  }
@@ -28585,25 +28732,14 @@ function formatMessageParts(msg, detail) {
28585
28732
  } else if (partType === "tool-result") {
28586
28733
  const toolName = part.toolName;
28587
28734
  if (toolName) {
28588
- const fullText = `[Tool Result: ${toolName}]\n${formatToolResultForObserver(part.output ?? part.result, { maxTokens: HIGH_DETAIL_TOOL_RESULT_TOKENS })}`;
28735
+ const fullText = `[Tool Result: ${toolName}]\n${formatToolResultForObserver(omitInlineMediaPayloads(part.output ?? part.result), { maxTokens: HIGH_DETAIL_TOOL_RESULT_TOKENS })}`;
28589
28736
  parts.push(makePart(msg, i, "tool-result", fullText, detail, toolName));
28590
28737
  }
28591
28738
  } else if (partType === "reasoning") {
28592
28739
  const reasoning = part.reasoning ?? part.text;
28593
28740
  if (reasoning) parts.push(makePart(msg, i, "reasoning", reasoning, detail));
28594
- } else if (partType === "image" || partType === "file") {
28595
- const filename = part.filename;
28596
- const label = filename ? `: ${filename}` : "";
28597
- const fullText = `[${partType === "image" ? "Image" : "File"}${label}]`;
28598
- parts.push({
28599
- messageId: msg.id,
28600
- partIndex: i,
28601
- role: msg.role,
28602
- type: partType,
28603
- text: fullText,
28604
- fullText
28605
- });
28606
- } else if (partType?.startsWith("data-")) {} else if (partType) {
28741
+ } else if (partType === "image" || partType === "file") parts.push(makePart(msg, i, partType, formatAttachmentPart(partType, part), detail));
28742
+ else if (partType?.startsWith("data-")) {} else if (partType) {
28607
28743
  const fullText = `[${partType}]`;
28608
28744
  parts.push({
28609
28745
  messageId: msg.id,
@@ -28776,6 +28912,29 @@ async function recallPart({ memory, threadId, resourceId, cursor, partIndex, cha
28776
28912
  note
28777
28913
  };
28778
28914
  }
28915
+ async function recallAttachmentView({ memory, threadId, resourceId, cursor, partIndex, threadScope, retrievalScope = "thread" }) {
28916
+ if (!memory || typeof memory.getMemoryStore !== "function") throw new Error("Memory instance is required for recall");
28917
+ if (!threadId) throw new Error("Thread ID is required for recall");
28918
+ const resolved = await resolveCursorMessage(memory, cursor, {
28919
+ resourceId,
28920
+ threadScope,
28921
+ enforceThreadScope: retrievalScope !== "resource"
28922
+ });
28923
+ if ("hint" in resolved) return { messages: resolved.hint };
28924
+ const rawPart = getMessageParts(resolved)[partIndex];
28925
+ const partType = rawPart?.type;
28926
+ 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.` };
28927
+ const resolvedAttachment = resolveViewableAttachment(rawPart);
28928
+ if ("note" in resolvedAttachment) return { messages: `${formatAttachmentPart(partType, rawPart)} — ${resolvedAttachment.note}` };
28929
+ return { content: [{
28930
+ type: "text",
28931
+ text: formatAttachmentPart(partType, rawPart)
28932
+ }, {
28933
+ type: partType === "image" ? "image" : "file",
28934
+ data: resolvedAttachment.data,
28935
+ mimeType: resolvedAttachment.mimeType
28936
+ }] };
28937
+ }
28779
28938
  async function recallMessages({ memory, threadId, resourceId, cursor, page = 1, limit = 20, detail = "low", partType, toolName, threadScope, retrievalScope = "thread", maxTokens = DEFAULT_MAX_RESULT_TOKENS }) {
28780
28939
  if (!memory) throw new Error("Memory instance is required for recall");
28781
28940
  if (!threadId) throw new Error("Thread ID is required for recall");
@@ -29061,11 +29220,15 @@ const recallTool = (_memoryConfig, options) => {
29061
29220
  type: "integer",
29062
29221
  minimum: 0,
29063
29222
  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\"."
29223
+ },
29224
+ viewAttachment: {
29225
+ type: "boolean",
29226
+ 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."
29064
29227
  }
29065
29228
  }
29066
29229
  },
29067
29230
  execute: async (inputData, context) => {
29068
- const { mode, query, cursor, threadId: explicitThreadId, anchor, page, limit, detail, partType, toolName, partIndex, charOffset, before, after } = inputData;
29231
+ const { mode, query, cursor, threadId: explicitThreadId, anchor, page, limit, detail, partType, toolName, partIndex, charOffset, before, after, viewAttachment } = inputData;
29069
29232
  const memory = context?.memory;
29070
29233
  const currentThreadId = context?.agent?.threadId;
29071
29234
  const resourceId = context?.agent?.resourceId;
@@ -29154,6 +29317,7 @@ const recallTool = (_memoryConfig, options) => {
29154
29317
  targetThreadId = resolved.threadId;
29155
29318
  }
29156
29319
  if (!targetThreadId) throw new Error("Thread ID is required for recall");
29320
+ 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." };
29157
29321
  if (!cursor) {
29158
29322
  const result = await recallThreadFromStart({
29159
29323
  memory,
@@ -29172,16 +29336,27 @@ const recallTool = (_memoryConfig, options) => {
29172
29336
  };
29173
29337
  return result;
29174
29338
  }
29175
- if (partIndex !== void 0 && partIndex !== null) return recallPart({
29176
- memory,
29177
- threadId: targetThreadId,
29178
- resourceId,
29179
- cursor,
29180
- partIndex,
29181
- charOffset,
29182
- threadScope,
29183
- retrievalScope
29184
- });
29339
+ if (partIndex !== void 0 && partIndex !== null) {
29340
+ if (viewAttachment) return recallAttachmentView({
29341
+ memory,
29342
+ threadId: targetThreadId,
29343
+ resourceId,
29344
+ cursor,
29345
+ partIndex,
29346
+ threadScope,
29347
+ retrievalScope
29348
+ });
29349
+ return recallPart({
29350
+ memory,
29351
+ threadId: targetThreadId,
29352
+ resourceId,
29353
+ cursor,
29354
+ partIndex,
29355
+ charOffset,
29356
+ threadScope,
29357
+ retrievalScope
29358
+ });
29359
+ }
29185
29360
  return recallMessages({
29186
29361
  memory,
29187
29362
  threadId: targetThreadId,
@@ -29195,7 +29370,8 @@ const recallTool = (_memoryConfig, options) => {
29195
29370
  threadScope,
29196
29371
  retrievalScope
29197
29372
  });
29198
- }
29373
+ },
29374
+ toModelOutput: recallAttachmentToModelOutput
29199
29375
  });
29200
29376
  };
29201
29377
  /**
@@ -30138,7 +30314,7 @@ function stripReflectionGroupMetadata(body) {
30138
30314
  return body.replace(/^_range:\s*`[^`]*`_\s*\n?/m, "").trim();
30139
30315
  }
30140
30316
  function generateAnchorId() {
30141
- return randomBytes(8).toString("hex");
30317
+ return Buffer.from(globalThis.crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(8))).toString("hex");
30142
30318
  }
30143
30319
  function wrapInObservationGroup(observations, range, id = generateAnchorId(), _sourceGroupIds, kind) {
30144
30320
  const content = observations.trim();
@@ -33462,7 +33638,7 @@ function inferReproIdRemap(preMessages, postMessages) {
33462
33638
  }
33463
33639
  function createOmReproCaptureDir(threadId, label) {
33464
33640
  const sanitizedThreadId = sanitizeCapturePathSegment(threadId);
33465
- const captureDir = join(process.cwd(), getOmReproCaptureDir(), sanitizedThreadId, `${Date.now()}-${label}-${randomUUID()}`);
33641
+ const captureDir = join(process.cwd(), getOmReproCaptureDir(), sanitizedThreadId, `${Date.now()}-${label}-${globalThis.crypto.randomUUID()}`);
33466
33642
  mkdirSync(captureDir, { recursive: true });
33467
33643
  return captureDir;
33468
33644
  }
@@ -37987,18 +38163,19 @@ Notes:
37987
38163
  const embedResult = await this.embedMessageContent(text);
37988
38164
  if (embedResult.embeddings.length === 0 || embedResult.dimension === void 0) return;
37989
38165
  const { indexName } = await this.createObservationEmbeddingIndex(embedResult.dimension);
37990
- const ids = embedResult.chunks.map((_, chunkIndex) => {
37991
- const hash = createHash("sha256").update(JSON.stringify([
38166
+ const ids = [];
38167
+ for (const [chunkIndex] of embedResult.chunks.entries()) {
38168
+ const hash = Buffer.from(await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(JSON.stringify([
37992
38169
  resourceId,
37993
38170
  threadId,
37994
38171
  groupId,
37995
38172
  chunkIndex
37996
- ])).digest();
38173
+ ]))));
37997
38174
  hash[6] = hash[6] & 15 | 128;
37998
38175
  hash[8] = hash[8] & 63 | 128;
37999
38176
  const hex = hash.toString("hex", 0, 16);
38000
- return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
38001
- });
38177
+ ids.push(`${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`);
38178
+ }
38002
38179
  await this.vector.upsert({
38003
38180
  indexName,
38004
38181
  ids,
@@ -49650,4 +49827,4 @@ const agentBuilderWorkflows = {
49650
49827
  //#endregion
49651
49828
  export { agentBuilderWorkflows };
49652
49829
 
49653
- //# sourceMappingURL=dist-CYk5xS3y.js.map
49830
+ //# sourceMappingURL=dist-B2EGPe0Y.js.map