@mastra/server 1.58.0-alpha.0 → 1.58.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.
Files changed (127) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/dist/_types/@mastra_schema-compat/dist/provider-compats/anthropic.d.ts +1 -1
  3. package/dist/{a2a-CnU9zaGR.js → a2a-8C4O2dVJ.js} +41 -5
  4. package/dist/a2a-8C4O2dVJ.js.map +1 -0
  5. package/dist/{a2a-DKnwIgiw.cjs → a2a-B6YkZ2i9.cjs} +872 -227
  6. package/dist/a2a-B6YkZ2i9.cjs.map +1 -0
  7. package/dist/{a2a-oM7aqLz4.cjs → a2a-MPoM5lzS.cjs} +41 -5
  8. package/dist/a2a-MPoM5lzS.cjs.map +1 -0
  9. package/dist/{a2a-uPi5sPwb.js → a2a-_D2EA4oa.js} +861 -228
  10. package/dist/a2a-_D2EA4oa.js.map +1 -0
  11. package/dist/{agent-builder-BDYN3r89.cjs → agent-builder-DAiJH1u2.cjs} +2 -2
  12. package/dist/{agent-builder-BDYN3r89.cjs.map → agent-builder-DAiJH1u2.cjs.map} +1 -1
  13. package/dist/{agent-builder-Dqy_qumV.js → agent-builder-gGFywDVq.js} +2 -2
  14. package/dist/{agent-builder-Dqy_qumV.js.map → agent-builder-gGFywDVq.js.map} +1 -1
  15. package/dist/{api-schema-manifest-7-NC9Dyc.cjs → api-schema-manifest-B3bC-D98.cjs} +2 -2
  16. package/dist/{api-schema-manifest-7-NC9Dyc.cjs.map → api-schema-manifest-B3bC-D98.cjs.map} +1 -1
  17. package/dist/{api-schema-manifest-C5hpdIE_.js → api-schema-manifest-B4J_QYOr.js} +2 -2
  18. package/dist/{api-schema-manifest-C5hpdIE_.js.map → api-schema-manifest-B4J_QYOr.js.map} +1 -1
  19. package/dist/{datasets-Cvix7Rms.cjs → datasets-BMeFvFwT.cjs} +43 -1
  20. package/dist/datasets-BMeFvFwT.cjs.map +1 -0
  21. package/dist/{datasets-dhXnHLAL.js → datasets-BeBH9Seg.js} +38 -2
  22. package/dist/datasets-BeBH9Seg.js.map +1 -0
  23. package/dist/{dist-DGqlUp0b.js → dist-BKRMiJcn.js} +215 -74
  24. package/dist/dist-BKRMiJcn.js.map +1 -0
  25. package/dist/{dist-COHIL6fR.cjs → dist-C2-SedDQ.cjs} +215 -74
  26. package/dist/dist-C2-SedDQ.cjs.map +1 -0
  27. package/dist/docs/SKILL.md +1 -1
  28. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  29. package/dist/docs/references/docs-agents-a2a.md +75 -2
  30. package/dist/docs/references/reference-server-routes.md +25 -11
  31. package/dist/route-builder-CIk5k35M.js.map +1 -1
  32. package/dist/route-builder-CgLVYL1c.cjs.map +1 -1
  33. package/dist/{routes-hSY4wTeS.cjs → routes-CZwPlO3-.cjs} +3 -2
  34. package/dist/routes-CZwPlO3-.cjs.map +1 -0
  35. package/dist/{routes-CRoTKPvQ.js → routes-HUaCyUb7.js} +4 -3
  36. package/dist/{routes-CRoTKPvQ.js.map → routes-HUaCyUb7.js.map} +1 -1
  37. package/dist/server/a2a/store.cjs +30 -2
  38. package/dist/server/a2a/store.cjs.map +1 -1
  39. package/dist/server/a2a/store.d.ts +21 -2
  40. package/dist/server/a2a/store.d.ts.map +1 -1
  41. package/dist/server/a2a/store.js +30 -3
  42. package/dist/server/a2a/store.js.map +1 -1
  43. package/dist/server/a2a/task-state.d.ts +4 -0
  44. package/dist/server/a2a/task-state.d.ts.map +1 -0
  45. package/dist/server/a2a/tasks.d.ts +1 -1
  46. package/dist/server/a2a/tasks.d.ts.map +1 -1
  47. package/dist/server/handlers/a2a.cjs +3 -1
  48. package/dist/server/handlers/a2a.d.ts +155 -12
  49. package/dist/server/handlers/a2a.d.ts.map +1 -1
  50. package/dist/server/handlers/a2a.js +2 -2
  51. package/dist/server/handlers/agent-builder.cjs +3 -3
  52. package/dist/server/handlers/agent-builder.js +3 -3
  53. package/dist/server/handlers/agent-controller.cjs +25 -6
  54. package/dist/server/handlers/agent-controller.cjs.map +1 -1
  55. package/dist/server/handlers/agent-controller.d.ts +4 -3
  56. package/dist/server/handlers/agent-controller.d.ts.map +1 -1
  57. package/dist/server/handlers/agent-controller.js +25 -6
  58. package/dist/server/handlers/agent-controller.js.map +1 -1
  59. package/dist/server/handlers/agent-versions.cjs +6 -0
  60. package/dist/server/handlers/agent-versions.cjs.map +1 -1
  61. package/dist/server/handlers/agent-versions.d.ts.map +1 -1
  62. package/dist/server/handlers/agent-versions.js +6 -0
  63. package/dist/server/handlers/agent-versions.js.map +1 -1
  64. package/dist/server/handlers/datasets.cjs +26 -11
  65. package/dist/server/handlers/datasets.cjs.map +1 -1
  66. package/dist/server/handlers/datasets.d.ts +136 -0
  67. package/dist/server/handlers/datasets.d.ts.map +1 -1
  68. package/dist/server/handlers/datasets.js +26 -11
  69. package/dist/server/handlers/datasets.js.map +1 -1
  70. package/dist/server/handlers/observability.cjs +20 -9
  71. package/dist/server/handlers/observability.cjs.map +1 -1
  72. package/dist/server/handlers/observability.d.ts.map +1 -1
  73. package/dist/server/handlers/observability.js +20 -9
  74. package/dist/server/handlers/observability.js.map +1 -1
  75. package/dist/server/handlers/stored-agents.cjs +16 -1
  76. package/dist/server/handlers/stored-agents.cjs.map +1 -1
  77. package/dist/server/handlers/stored-agents.d.ts.map +1 -1
  78. package/dist/server/handlers/stored-agents.js +16 -1
  79. package/dist/server/handlers/stored-agents.js.map +1 -1
  80. package/dist/server/handlers/system.cjs +1 -1
  81. package/dist/server/handlers/system.js +1 -1
  82. package/dist/server/handlers/validate-agent-instructions.cjs +52 -0
  83. package/dist/server/handlers/validate-agent-instructions.cjs.map +1 -0
  84. package/dist/server/handlers/validate-agent-instructions.d.ts +13 -0
  85. package/dist/server/handlers/validate-agent-instructions.d.ts.map +1 -0
  86. package/dist/server/handlers/validate-agent-instructions.js +51 -0
  87. package/dist/server/handlers/validate-agent-instructions.js.map +1 -0
  88. package/dist/server/handlers/workflows.cjs +105 -2
  89. package/dist/server/handlers/workflows.cjs.map +1 -1
  90. package/dist/server/handlers/workflows.d.ts +9 -0
  91. package/dist/server/handlers/workflows.d.ts.map +1 -1
  92. package/dist/server/handlers/workflows.js +104 -3
  93. package/dist/server/handlers/workflows.js.map +1 -1
  94. package/dist/server/handlers.cjs +1 -1
  95. package/dist/server/handlers.js +1 -1
  96. package/dist/server/schemas/a2a.d.ts +70 -6
  97. package/dist/server/schemas/a2a.d.ts.map +1 -1
  98. package/dist/server/schemas/datasets.d.ts +53 -0
  99. package/dist/server/schemas/datasets.d.ts.map +1 -1
  100. package/dist/server/schemas/index.cjs +5 -4
  101. package/dist/server/schemas/index.js +5 -5
  102. package/dist/server/schemas/workflows.d.ts +8 -0
  103. package/dist/server/schemas/workflows.d.ts.map +1 -1
  104. package/dist/server/server-adapter/index.cjs +1 -1
  105. package/dist/server/server-adapter/index.js +1 -1
  106. package/dist/server/server-adapter/routes/a2a.d.ts +116 -8
  107. package/dist/server/server-adapter/routes/a2a.d.ts.map +1 -1
  108. package/dist/server/server-adapter/routes/datasets.d.ts +136 -0
  109. package/dist/server/server-adapter/routes/datasets.d.ts.map +1 -1
  110. package/dist/server/server-adapter/routes/workflows.d.ts +7 -1
  111. package/dist/server/server-adapter/routes/workflows.d.ts.map +1 -1
  112. package/dist/{workflows-DPW6FrY0.js → workflows-CMU5dz_4.js} +7 -2
  113. package/dist/workflows-CMU5dz_4.js.map +1 -0
  114. package/dist/{workflows-XfiENvkF.cjs → workflows-Dzxr6cmf.cjs} +12 -1
  115. package/dist/workflows-Dzxr6cmf.cjs.map +1 -0
  116. package/package.json +8 -8
  117. package/dist/a2a-CnU9zaGR.js.map +0 -1
  118. package/dist/a2a-DKnwIgiw.cjs.map +0 -1
  119. package/dist/a2a-oM7aqLz4.cjs.map +0 -1
  120. package/dist/a2a-uPi5sPwb.js.map +0 -1
  121. package/dist/datasets-Cvix7Rms.cjs.map +0 -1
  122. package/dist/datasets-dhXnHLAL.js.map +0 -1
  123. package/dist/dist-COHIL6fR.cjs.map +0 -1
  124. package/dist/dist-DGqlUp0b.js.map +0 -1
  125. package/dist/routes-hSY4wTeS.cjs.map +0 -1
  126. package/dist/workflows-DPW6FrY0.js.map +0 -1
  127. package/dist/workflows-XfiENvkF.cjs.map +0 -1
@@ -5962,7 +5962,7 @@ function splitLines(text) {
5962
5962
  return result;
5963
5963
  }
5964
5964
  //#endregion
5965
- //#region ../memory/dist/src-Cwt9gefz.js
5965
+ //#region ../memory/dist/src-CdqJP57F.js
5966
5966
  var __defProp$3 = Object.defineProperty;
5967
5967
  var __exportAll = (all, no_symbols) => {
5968
5968
  let target = {};
@@ -20725,6 +20725,7 @@ var Extractor = class Extractor {
20725
20725
  includePreviousExtraction;
20726
20726
  metadataKeyPath;
20727
20727
  onExtracted;
20728
+ retryStructuredExtractionOnEmptyObject;
20728
20729
  /** @internal */
20729
20730
  internal;
20730
20731
  instructionsConfig;
@@ -20747,6 +20748,7 @@ var Extractor = class Extractor {
20747
20748
  this.includePreviousExtraction = config.includePreviousExtraction ?? true;
20748
20749
  this.metadataKeyPath = config.metadataKeyPath ?? `extracted.${slug}`;
20749
20750
  this.onExtracted = config.onExtracted;
20751
+ this.retryStructuredExtractionOnEmptyObject = config.retryStructuredExtractionOnEmptyObject ?? false;
20750
20752
  this.internal = internal;
20751
20753
  }
20752
20754
  async resolve(context) {
@@ -20759,7 +20761,8 @@ var Extractor = class Extractor {
20759
20761
  ...schema ? { schema } : {},
20760
20762
  includePreviousExtraction: this.includePreviousExtraction,
20761
20763
  metadataKeyPath: this.metadataKeyPath,
20762
- onExtracted: this.onExtracted
20764
+ onExtracted: this.onExtracted,
20765
+ retryStructuredExtractionOnEmptyObject: this.retryStructuredExtractionOnEmptyObject
20763
20766
  }, this.internal);
20764
20767
  }
20765
20768
  };
@@ -21078,6 +21081,9 @@ if (OM_DEBUG_LOG) {
21078
21081
  function isAbortError$1(error, abortSignal) {
21079
21082
  return abortSignal?.aborted === true || error instanceof DOMException && error.name === "AbortError" || error instanceof Error && error.name === "AbortError";
21080
21083
  }
21084
+ function shouldRetryEmptyStructuredObject(object, extractors) {
21085
+ return Object.keys(object).length === 0 && extractors.some((extractor) => extractor.retryStructuredExtractionOnEmptyObject);
21086
+ }
21081
21087
  async function extractStructuredValues(opts) {
21082
21088
  const structuredExtractors = (opts.extractors ?? []).filter((extractor) => extractor.mode === "structured");
21083
21089
  if (structuredExtractors.length === 0) return {
@@ -21114,8 +21120,10 @@ ${extractorInstructions}${priorLines.length > 0 ? `\n\n## Prior Extracted Values
21114
21120
  return output.object;
21115
21121
  };
21116
21122
  let object;
21123
+ let retryEmptyObject = false;
21117
21124
  try {
21118
21125
  object = await generateWithStructuredOutput();
21126
+ retryEmptyObject = shouldRetryEmptyStructuredObject(object, structuredExtractors);
21119
21127
  } catch (error) {
21120
21128
  if (isAbortError$1(error, opts.abortSignal)) throw error;
21121
21129
  try {
@@ -21132,6 +21140,19 @@ ${extractorInstructions}${priorLines.length > 0 ? `\n\n## Prior Extracted Values
21132
21140
  };
21133
21141
  }
21134
21142
  }
21143
+ if (retryEmptyObject) try {
21144
+ object = await generateWithStructuredOutput(_mastra_core_features.coreFeatures.has("json-prompt-injection:inline") ? "inline" : true);
21145
+ } catch (fallbackError) {
21146
+ if (isAbortError$1(fallbackError, opts.abortSignal)) throw fallbackError;
21147
+ const message = fallbackError instanceof Error ? fallbackError.message : String(fallbackError);
21148
+ return {
21149
+ values,
21150
+ failures: structuredExtractors.map((extractor) => ({
21151
+ slug: extractor.slug,
21152
+ error: message
21153
+ }))
21154
+ };
21155
+ }
21135
21156
  for (const extractor of structuredExtractors) {
21136
21157
  const value = object[extractor.slug];
21137
21158
  if (value === void 0 || value === null || value === "") continue;
@@ -24415,6 +24436,17 @@ var TokenCounter = class TokenCounter {
24415
24436
  toolResultDelta
24416
24437
  };
24417
24438
  }
24439
+ if (invocation.state === "output-error") {
24440
+ toolResultDelta++;
24441
+ const errorText = invocation.errorText;
24442
+ const errorMessage = typeof errorText === "string" ? errorText : "Tool execution failed";
24443
+ tokens += this.readOrPersistPartEstimate(part, "tool-result-error", errorMessage);
24444
+ return {
24445
+ tokens,
24446
+ overheadDelta,
24447
+ toolResultDelta
24448
+ };
24449
+ }
24418
24450
  throw new Error(`Unhandled tool-invocation state '${part.toolInvocation?.state}' in token counting for part type '${part.type}'`);
24419
24451
  }
24420
24452
  if (typeof part.type === "string" && part.type.startsWith("data-")) return {
@@ -24636,6 +24668,7 @@ var WorkingMemoryExtractor = class extends Extractor {
24636
24668
  name: "Working Memory",
24637
24669
  includePreviousExtraction: false,
24638
24670
  metadataKeyPath: false,
24671
+ retryStructuredExtractionOnEmptyObject: true,
24639
24672
  instructions: async (context) => buildWorkingMemoryInstructions(await getWorkingMemoryDetails(context)),
24640
24673
  schema: async (context) => {
24641
24674
  return (await getWorkingMemoryDetails(context)).usesSchema ? zod.z.union([zod.z.record(zod.z.string(), zod.z.unknown()), zod.z.null()]) : void 0;
@@ -24782,9 +24815,10 @@ async function listThreadsForResource({ memory, resourceId, currentThreadId, pag
24782
24815
  hasMore
24783
24816
  };
24784
24817
  }
24818
+ const SEARCH_NOT_CONFIGURED_MESSAGE = "Search is not configured. Enable it with `retrieval: { vector: true }` and configure a vector store and embedder on your Memory instance.";
24785
24819
  async function searchMessagesForResource({ memory, resourceId, currentThreadId, query, topK = 10, maxTokens = DEFAULT_MAX_RESULT_TOKENS, before, after, threadScope }) {
24786
24820
  if (!memory.searchMessages) return {
24787
- results: "Search is not configured. Enable it with `retrieval: { vector: true }` and configure a vector store and embedder on your Memory instance.",
24821
+ results: SEARCH_NOT_CONFIGURED_MESSAGE,
24788
24822
  count: 0
24789
24823
  };
24790
24824
  const MAX_TOPK = 20;
@@ -25330,9 +25364,16 @@ async function recallThreadFromStart({ memory, threadId, resourceId, page = 1, l
25330
25364
  }
25331
25365
  const recallTool = (_memoryConfig, options) => {
25332
25366
  const isResourceScope = (options?.retrievalScope ?? "thread") === "resource";
25367
+ const searchEnabled = options?.searchEnabled ?? true;
25368
+ const description = isResourceScope ? `Browse conversation history. Use mode="threads" to list all threads for the current user. Use mode="messages" (default) to browse messages in the current thread or pass threadId to browse another thread in the active resource. When mode="messages" has no cursor or threadId, it defaults to the current thread and says so at the top of the result. If you pass only a cursor, it must belong to the current thread.${searchEnabled ? " Use mode=\"search\" to find messages by content across all threads." : ""}` : `Browse conversation history in the current thread. Use mode="messages" (default) to page through messages near a cursor.${searchEnabled ? " Use mode=\"search\" to find messages by content in this thread." : ""} Use mode="threads" to get the current thread's ID and title.`;
25369
+ const modeEnum = searchEnabled ? [
25370
+ "messages",
25371
+ "threads",
25372
+ "search"
25373
+ ] : ["messages", "threads"];
25333
25374
  return (0, _mastra_core_tools.createTool)({
25334
25375
  id: "recall",
25335
- description: isResourceScope ? "Browse conversation history. Use mode=\"threads\" to list all threads for the current user. Use mode=\"messages\" (default) to browse messages in the current thread or pass threadId to browse another thread in the active resource. When mode=\"messages\" has no cursor or threadId, it defaults to the current thread and says so at the top of the result. If you pass only a cursor, it must belong to the current thread. 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.",
25376
+ description,
25336
25377
  inputSchema: {
25337
25378
  $schema: "http://json-schema.org/draft-07/schema#",
25338
25379
  type: "object",
@@ -25340,12 +25381,8 @@ const recallTool = (_memoryConfig, options) => {
25340
25381
  ...isResourceScope ? {
25341
25382
  mode: {
25342
25383
  type: "string",
25343
- enum: [
25344
- "messages",
25345
- "threads",
25346
- "search"
25347
- ],
25348
- description: "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."
25384
+ enum: modeEnum,
25385
+ description: `What to retrieve. "messages" (default) pages through message history. "threads" lists all threads for the current user.${searchEnabled ? " \"search\" finds messages by semantic similarity across all threads." : ""}`
25349
25386
  },
25350
25387
  threadId: {
25351
25388
  type: "string",
@@ -25362,18 +25399,14 @@ const recallTool = (_memoryConfig, options) => {
25362
25399
  }
25363
25400
  } : { mode: {
25364
25401
  type: "string",
25365
- enum: [
25366
- "messages",
25367
- "threads",
25368
- "search"
25369
- ],
25370
- description: "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."
25402
+ enum: modeEnum,
25403
+ description: `What to retrieve. "messages" (default) pages through message history. "threads" returns info about the current thread.${searchEnabled ? " \"search\" finds messages by semantic similarity in this thread." : ""}`
25371
25404
  } },
25372
- query: {
25405
+ ...searchEnabled ? { query: {
25373
25406
  type: "string",
25374
25407
  minLength: 1,
25375
25408
  description: "Search query for mode=\"search\". Finds messages semantically similar to this text."
25376
- },
25409
+ } } : {},
25377
25410
  cursor: {
25378
25411
  type: "string",
25379
25412
  minLength: 1,
@@ -25434,6 +25467,10 @@ const recallTool = (_memoryConfig, options) => {
25434
25467
  if (!memory) throw new Error("Memory instance is required for recall");
25435
25468
  if (explicitThreadId === "current" && !currentThreadId) throw new Error("Could not resolve current thread.");
25436
25469
  if (mode === "search") {
25470
+ if (!searchEnabled) return {
25471
+ results: SEARCH_NOT_CONFIGURED_MESSAGE,
25472
+ count: 0
25473
+ };
25437
25474
  if (!query) throw new Error("query is required for mode=\"search\"");
25438
25475
  if (!resourceId) throw new Error("Resource ID is required for recall");
25439
25476
  return searchMessagesForResource({
@@ -26377,6 +26414,24 @@ function getUnobservedPartsPreservingToolCallPairs(message) {
26377
26414
  return preservedCalls.length > 0 ? [...preservedCalls, ...unobservedParts] : unobservedParts;
26378
26415
  }
26379
26416
  /**
26417
+ * Get the messages Observational Memory is allowed to work with.
26418
+ *
26419
+ * Messages supplied through the `context` option are per-run ephemeral input. Core's
26420
+ * persistence contract already treats them as never-persist: `MessageStateManager` routes
26421
+ * them into `userContextMessages`, and `drainUnsavedMessages` only drains input/response.
26422
+ *
26423
+ * OM builds its windows from `get.all.db()`, which includes context messages, and then
26424
+ * seals and persists candidates directly — turning ephemeral context into durable user
26425
+ * messages. Excluding them here keeps OM's window, sealing, persistence and token
26426
+ * accounting consistent with that contract.
26427
+ */
26428
+ function getObservableMessages(messageList) {
26429
+ const allMessages = messageList.get.all.db();
26430
+ const contextMessageIds = messageList.makeMessageSourceChecker().context;
26431
+ if (contextMessageIds.size === 0) return allMessages;
26432
+ return allMessages.filter((message) => !contextMessageIds.has(message.id));
26433
+ }
26434
+ /**
26380
26435
  * Safely extract buffered observation chunks from a record.
26381
26436
  * Handles both array and JSON-string formats, returning empty array if malformed.
26382
26437
  */
@@ -26389,7 +26444,7 @@ function getUnobservedPartsPreservingToolCallPairs(message) {
26389
26444
  */
26390
26445
  function filterObservedMessages(opts) {
26391
26446
  const { messageList, record } = opts;
26392
- const allMessages = messageList.get.all.db();
26447
+ const allMessages = getObservableMessages(messageList);
26393
26448
  const useMarkerBoundaryPruning = opts.useMarkerBoundaryPruning ?? true;
26394
26449
  const preserveMessageIds = opts.preserveMessageIds ?? /* @__PURE__ */ new Set();
26395
26450
  const observedIds = new Set(Array.isArray(record?.observedMessageIds) ? record.observedMessageIds : []);
@@ -26801,7 +26856,7 @@ var ObservationStrategy = class ObservationStrategy {
26801
26856
  transient: true
26802
26857
  }).catch(() => {});
26803
26858
  const markerThreadId = marker.data?.threadId ?? this.opts.threadId;
26804
- await this.persistMarkerToStorage(marker, markerThreadId, this.opts.resourceId);
26859
+ if (!await this.persistMarkerToMessage(marker, this.opts.messageList, markerThreadId, this.opts.resourceId)) await this.persistMarkerToStorage(marker, markerThreadId, this.opts.resourceId);
26805
26860
  }
26806
26861
  getObservationMarkerConfig() {
26807
26862
  return {
@@ -26929,10 +26984,14 @@ var ObservationStrategy = class ObservationStrategy {
26929
26984
  /**
26930
26985
  * Persist a marker part on the last assistant message in a MessageList
26931
26986
  * AND save the updated message to the DB.
26987
+ *
26988
+ * @returns true when a marker was placed on an assistant message, false when
26989
+ * no list was provided or the list contains no assistant message (caller
26990
+ * should fall back to `persistMarkerToStorage`).
26932
26991
  */
26933
26992
  async persistMarkerToMessage(marker, messageList, threadId, resourceId) {
26934
- if (!messageList) return;
26935
- const allMsgs = messageList.get.all.db();
26993
+ if (!messageList) return false;
26994
+ const allMsgs = getObservableMessages(messageList);
26936
26995
  for (let i = allMsgs.length - 1; i >= 0; i--) {
26937
26996
  const msg = allMsgs[i];
26938
26997
  if (msg?.role === "assistant" && msg.content?.parts && Array.isArray(msg.content.parts)) {
@@ -26947,9 +27006,10 @@ var ObservationStrategy = class ObservationStrategy {
26947
27006
  } catch (e) {
26948
27007
  omDebug(`[OM:persistMarker] failed to save marker to DB: ${e}`);
26949
27008
  }
26950
- return;
27009
+ return true;
26951
27010
  }
26952
27011
  }
27012
+ return false;
26953
27013
  }
26954
27014
  };
26955
27015
  var SyncObservationStrategy = class extends ObservationStrategy {
@@ -27746,6 +27806,12 @@ var ObservationStep = class {
27746
27806
  stepNumber;
27747
27807
  _prepared = false;
27748
27808
  _context;
27809
+ /**
27810
+ * True when this step seeded an empty assistant response message for a step-0
27811
+ * observation. While set, the response-id rotation hook must NOT run — rotating
27812
+ * would orphan the seed (markers would sit on a message the agent never streams into).
27813
+ */
27814
+ seededResponseMessage = false;
27749
27815
  constructor(turn, stepNumber) {
27750
27816
  this.turn = turn;
27751
27817
  this.stepNumber = stepNumber;
@@ -27792,7 +27858,7 @@ var ObservationStep = class {
27792
27858
  let didThresholdCleanup = false;
27793
27859
  let observerExchange;
27794
27860
  if (this.stepNumber === 0) {
27795
- const step0Messages = messageList.get.all.db();
27861
+ const step0Messages = getObservableMessages(messageList);
27796
27862
  const activation = await om.activate({
27797
27863
  threadId,
27798
27864
  resourceId,
@@ -27824,7 +27890,7 @@ var ObservationStep = class {
27824
27890
  currentModel: this.turn.actorModelContext,
27825
27891
  requestContext: this.turn.requestContext,
27826
27892
  observabilityContext: this.turn.observabilityContext,
27827
- lastActivityAt: getLastActivityFromMessages(messageList.get.all.db()),
27893
+ lastActivityAt: getLastActivityFromMessages(getObservableMessages(messageList)),
27828
27894
  reflectionHooks: om.composeHooks(void 0, {
27829
27895
  threadId,
27830
27896
  resourceId,
@@ -27834,7 +27900,7 @@ var ObservationStep = class {
27834
27900
  await this.turn.refreshRecord();
27835
27901
  if (this.turn.record.generationCount > preReflectGeneration) reflected = true;
27836
27902
  }
27837
- const allMsgsForToolCheck = messageList.get.all.db();
27903
+ const allMsgsForToolCheck = getObservableMessages(messageList);
27838
27904
  const lastMessage = allMsgsForToolCheck[allMsgsForToolCheck.length - 1];
27839
27905
  const pendingStepMessages = [...messageList.get.input.db(), ...messageList.get.response.db()];
27840
27906
  const latestStepParts = [...getLatestStepParts(lastMessage?.content?.parts ?? []), ...pendingStepMessages.flatMap((msg) => getLatestStepParts(msg.content?.parts ?? []))];
@@ -27843,10 +27909,10 @@ var ObservationStep = class {
27843
27909
  let statusSnapshot = await om.getStatus({
27844
27910
  threadId,
27845
27911
  resourceId,
27846
- messages: messageList.get.all.db()
27912
+ messages: getObservableMessages(messageList)
27847
27913
  });
27848
27914
  if (statusSnapshot.shouldBuffer && !hasIncompleteToolCalls) {
27849
- const allMessages = messageList.get.all.db();
27915
+ const allMessages = getObservableMessages(messageList);
27850
27916
  const unobservedMessages = om.getUnobservedMessages(allMessages, statusSnapshot.record);
27851
27917
  const candidates = om.getUnobservedMessages(unobservedMessages, statusSnapshot.record, { excludeBuffered: true });
27852
27918
  if (candidates.length > 0) {
@@ -27874,15 +27940,41 @@ var ObservationStep = class {
27874
27940
  });
27875
27941
  buffered = true;
27876
27942
  }
27877
- if (this.stepNumber > 0) {
27878
- const newInput = messageList.clear.input.db();
27879
- const newOutput = messageList.clear.response.db();
27880
- const messagesToSave = [...newInput, ...newOutput];
27881
- if (messagesToSave.length > 0) {
27882
- await om.persistMessages(messagesToSave, threadId, resourceId);
27883
- for (const msg of messagesToSave) messageList.add(msg, "memory");
27943
+ const willObserveNow = statusSnapshot.shouldObserve && !hasIncompleteToolCalls;
27944
+ /** In-flight message ids the step-0 cleanup must never remove from live context. */
27945
+ let step0PreserveIds;
27946
+ if (this.stepNumber > 0 || willObserveNow) {
27947
+ if (this.stepNumber > 0) {
27948
+ const newInput = messageList.clear.input.db();
27949
+ const newOutput = messageList.clear.response.db();
27950
+ const messagesToSave = [...newInput, ...newOutput];
27951
+ if (messagesToSave.length > 0) {
27952
+ await om.persistMessages(messagesToSave, threadId, resourceId);
27953
+ for (const msg of messagesToSave) messageList.add(msg, "memory");
27954
+ }
27955
+ } else {
27956
+ const pending = [...messageList.get.input.db(), ...messageList.get.response.db()];
27957
+ if (pending.length > 0) await om.persistMessages(pending, threadId, resourceId);
27958
+ step0PreserveIds = pending.map((msg) => msg.id);
27959
+ }
27960
+ if (this.stepNumber === 0 && willObserveNow && this.turn.responseMessageId) {
27961
+ const seed = {
27962
+ id: this.turn.responseMessageId,
27963
+ role: "assistant",
27964
+ content: {
27965
+ format: 2,
27966
+ parts: []
27967
+ },
27968
+ type: "text",
27969
+ createdAt: /* @__PURE__ */ new Date(),
27970
+ threadId,
27971
+ resourceId
27972
+ };
27973
+ messageList.add(seed, "response");
27974
+ this.seededResponseMessage = true;
27975
+ omDebug(`[OM:step0] seeded response message ${seed.id} for step-0 observation markers`);
27884
27976
  }
27885
- if (statusSnapshot.shouldObserve && !hasIncompleteToolCalls) {
27977
+ if (willObserveNow) {
27886
27978
  const preObsGeneration = this.turn.record.generationCount;
27887
27979
  const obsResult = await this.runThresholdObservation();
27888
27980
  observerExchange = obsResult.observerExchange;
@@ -27896,7 +27988,8 @@ var ObservationStep = class {
27896
27988
  resourceId,
27897
27989
  messages: messageList,
27898
27990
  observedMessageIds: observedIds,
27899
- retentionFloor: minRemaining
27991
+ retentionFloor: minRemaining,
27992
+ preserveMessageIds: step0PreserveIds
27900
27993
  });
27901
27994
  if (statusSnapshot.asyncObservationEnabled) await om.resetBufferingState({
27902
27995
  threadId,
@@ -27911,7 +28004,7 @@ var ObservationStep = class {
27911
28004
  statusSnapshot = await om.getStatus({
27912
28005
  threadId,
27913
28006
  resourceId,
27914
- messages: messageList.get.all.db()
28007
+ messages: getObservableMessages(messageList)
27915
28008
  });
27916
28009
  }
27917
28010
  const otherThreadsContext = await this.turn.refreshOtherThreadsContext();
@@ -27960,10 +28053,11 @@ var ObservationStep = class {
27960
28053
  const { threadId, resourceId, messageList } = this.turn;
27961
28054
  const om = this.turn.om;
27962
28055
  await om.waitForBuffering(threadId, resourceId);
28056
+ const observableMessages = this.seededResponseMessage ? getObservableMessages(messageList).filter((msg) => msg.id !== this.turn.responseMessageId) : getObservableMessages(messageList);
27963
28057
  const freshStatus = await om.getStatus({
27964
28058
  threadId,
27965
28059
  resourceId,
27966
- messages: messageList.get.all.db()
28060
+ messages: observableMessages
27967
28061
  });
27968
28062
  if (!freshStatus.shouldObserve) return {
27969
28063
  succeeded: false,
@@ -27973,7 +28067,7 @@ var ObservationStep = class {
27973
28067
  const activation = await om.activate({
27974
28068
  threadId,
27975
28069
  resourceId,
27976
- messages: messageList.get.all.db(),
28070
+ messages: observableMessages,
27977
28071
  currentModel: this.turn.actorModelContext,
27978
28072
  writer: this.turn.writer,
27979
28073
  messageList
@@ -27989,7 +28083,7 @@ var ObservationStep = class {
27989
28083
  currentModel: this.turn.actorModelContext,
27990
28084
  requestContext: this.turn.requestContext,
27991
28085
  observabilityContext: this.turn.observabilityContext,
27992
- lastActivityAt: getLastActivityFromMessages(messageList.get.all.db()),
28086
+ lastActivityAt: getLastActivityFromMessages(getObservableMessages(messageList)),
27993
28087
  reflectionHooks: om.composeHooks(void 0, {
27994
28088
  threadId,
27995
28089
  resourceId,
@@ -28006,7 +28100,8 @@ var ObservationStep = class {
28006
28100
  const obsResult = await om.observe({
28007
28101
  threadId,
28008
28102
  resourceId,
28009
- messages: messageList.get.all.db(),
28103
+ messages: observableMessages,
28104
+ messageList,
28010
28105
  trigger: "turn-sync",
28011
28106
  requestContext: this.turn.requestContext,
28012
28107
  writer: this.turn.writer,
@@ -28014,7 +28109,7 @@ var ObservationStep = class {
28014
28109
  });
28015
28110
  if (obsResult.observed) {
28016
28111
  const observedMessageIds = new Set(obsResult.record.observedMessageIds ?? []);
28017
- const liveMessages = messageList.get.all.db();
28112
+ const liveMessages = getObservableMessages(messageList);
28018
28113
  let latestObservedIndex = -1;
28019
28114
  for (let i = liveMessages.length - 1; i >= 0; i--) {
28020
28115
  const message = liveMessages[i];
@@ -28023,10 +28118,12 @@ var ObservationStep = class {
28023
28118
  break;
28024
28119
  }
28025
28120
  }
28026
- const messageToSeal = latestObservedIndex >= 0 ? liveMessages[latestObservedIndex] : void 0;
28121
+ let messageToSeal = latestObservedIndex >= 0 ? liveMessages[latestObservedIndex] : void 0;
28122
+ if (this.stepNumber === 0 && messageToSeal?.role !== "assistant") messageToSeal = void 0;
28027
28123
  const messagesToSeal = messageToSeal ? [messageToSeal] : [];
28028
28124
  om.sealMessagesForBuffering(messagesToSeal);
28029
- try {
28125
+ if (this.seededResponseMessage) omDebug("[OM:observe] skipping response-id rotation — step-0 seeded response message holds the active id");
28126
+ else try {
28030
28127
  await this.turn.hooks?.onSyncObservationComplete?.();
28031
28128
  } catch (error) {
28032
28129
  omDebug(`[OM:observe] onSyncObservationComplete hook failed: ${error instanceof Error ? error.message : String(error)}`);
@@ -28085,6 +28182,8 @@ var ObservationTurn = class {
28085
28182
  sendSignal;
28086
28183
  /** Current actor model for this step. Updated by the processor before prepare(). */
28087
28184
  actorModelContext;
28185
+ /** The active assistant response message ID for this step. Updated by the processor before prepare(). */
28186
+ responseMessageId;
28088
28187
  /** Processor-provided hooks for turn/step lifecycle integration. */
28089
28188
  hooks;
28090
28189
  constructor(opts) {
@@ -28183,7 +28282,7 @@ var ObservationTurn = class {
28183
28282
  const asyncObservationEnabled = this.om.buffering.isAsyncObservationEnabled();
28184
28283
  const bufferOnIdle = this.om.getObservationConfig().bufferOnIdle;
28185
28284
  if (asyncObservationEnabled && bufferOnIdle) {
28186
- const allMessages = this.messageList.get.all.db();
28285
+ const allMessages = getObservableMessages(this.messageList);
28187
28286
  const record = this._record;
28188
28287
  const unobservedMessages = this.om.getUnobservedMessages(allMessages, record);
28189
28288
  if (unobservedMessages.length > 0) this.om.buffer({
@@ -28549,7 +28648,7 @@ function getCurrentModel$1(model) {
28549
28648
  return formatModelContext$1(model?.provider, model?.modelId);
28550
28649
  }
28551
28650
  function getLastModelFromMessageList(messageList) {
28552
- const messages = messageList?.get.all.db();
28651
+ const messages = messageList ? getObservableMessages(messageList) : void 0;
28553
28652
  if (!messages) return void 0;
28554
28653
  for (let i = messages.length - 1; i >= 0; i--) {
28555
28654
  const message = messages[i];
@@ -30129,7 +30228,7 @@ var ObservationalMemory = class ObservationalMemory {
30129
30228
  */
30130
30229
  async persistMarkerToMessage(marker, messageList, threadId, resourceId) {
30131
30230
  if (!messageList) return;
30132
- const allMsgs = messageList.get.all.db();
30231
+ const allMsgs = getObservableMessages(messageList);
30133
30232
  for (let i = allMsgs.length - 1; i >= 0; i--) {
30134
30233
  const msg = allMsgs[i];
30135
30234
  if (msg?.role === "assistant" && msg.content?.parts && Array.isArray(msg.content.parts)) {
@@ -30745,6 +30844,7 @@ ${formattedMessages}
30745
30844
  */
30746
30845
  async getObservedMessageIdsForCleanup(opts) {
30747
30846
  const { threadId, resourceId, messages, observedMessageIds, retentionFloor } = opts;
30847
+ const preserveSet = opts.preserveMessageIds?.length ? new Set(opts.preserveMessageIds) : null;
30748
30848
  const record = await this.getOrCreateRecord(threadId, resourceId);
30749
30849
  const effectiveObservedIds = observedMessageIds && observedMessageIds.length > 0 ? observedMessageIds : Array.isArray(record.observedMessageIds) ? record.observedMessageIds : [];
30750
30850
  if (effectiveObservedIds.length === 0) return [];
@@ -30756,6 +30856,10 @@ ${formattedMessages}
30756
30856
  const retentionCounter = typeof retentionFloor === "number" ? new TokenCounter() : null;
30757
30857
  for (const msg of messages) {
30758
30858
  if (!msg?.id || msg.id === "om-continuation" || !observedSet.has(msg.id)) continue;
30859
+ if (preserveSet?.has(msg.id)) {
30860
+ skipped += 1;
30861
+ continue;
30862
+ }
30759
30863
  const unobservedParts = getUnobservedParts(msg);
30760
30864
  const totalParts = msg.content?.parts?.length ?? 0;
30761
30865
  if (unobservedParts.length > 0 && unobservedParts.length < totalParts) {
@@ -30800,9 +30904,9 @@ ${formattedMessages}
30800
30904
  */
30801
30905
  /** @internal Used by ObservationStep. */
30802
30906
  async cleanupMessages(opts) {
30803
- const { threadId, resourceId, observedMessageIds, retentionFloor } = opts;
30907
+ const { threadId, resourceId, observedMessageIds, retentionFloor, preserveMessageIds } = opts;
30804
30908
  const messageList = this.isMessageList(opts.messages) ? opts.messages : void 0;
30805
- const allMsgs = messageList ? messageList.get.all.db() : opts.messages;
30909
+ const allMsgs = messageList ? getObservableMessages(messageList) : opts.messages;
30806
30910
  let markerIdx = -1;
30807
30911
  let markerMsg = null;
30808
30912
  for (let i = allMsgs.length - 1; i >= 0; i--) {
@@ -30821,7 +30925,8 @@ ${formattedMessages}
30821
30925
  resourceId,
30822
30926
  messages: allMsgs,
30823
30927
  observedMessageIds,
30824
- retentionFloor
30928
+ retentionFloor,
30929
+ preserveMessageIds
30825
30930
  });
30826
30931
  if (messageList) {
30827
30932
  if (idsToRemoveList.length > 0) messageList.removeByIds(idsToRemoveList);
@@ -30833,18 +30938,21 @@ ${formattedMessages}
30833
30938
  if (markerMsg && markerIdx !== -1) {
30834
30939
  const idsToRemove = [];
30835
30940
  const messagesToSave = [];
30941
+ const preserveSet = preserveMessageIds?.length ? new Set(preserveMessageIds) : null;
30836
30942
  for (let i = 0; i < markerIdx; i++) {
30837
30943
  const msg = allMsgs[i];
30838
- if (msg?.id && msg.id !== "om-continuation") {
30944
+ if (msg?.id && msg.id !== "om-continuation" && !preserveSet?.has(msg.id)) {
30839
30945
  idsToRemove.push(msg.id);
30840
30946
  messagesToSave.push(msg);
30841
30947
  }
30842
30948
  }
30843
30949
  messagesToSave.push(markerMsg);
30844
- const unobservedParts = getUnobservedParts(markerMsg);
30845
- if (unobservedParts.length === 0) {
30846
- if (markerMsg.id) idsToRemove.push(markerMsg.id);
30847
- } else if (unobservedParts.length < (markerMsg.content?.parts?.length ?? 0)) markerMsg.content.parts = unobservedParts;
30950
+ if (!Boolean(markerMsg.id && preserveSet?.has(markerMsg.id))) {
30951
+ const unobservedParts = getUnobservedParts(markerMsg);
30952
+ if (unobservedParts.length === 0) {
30953
+ if (markerMsg.id) idsToRemove.push(markerMsg.id);
30954
+ } else if (unobservedParts.length < (markerMsg.content?.parts?.length ?? 0)) markerMsg.content.parts = unobservedParts;
30955
+ }
30848
30956
  if (messageList) {
30849
30957
  if (idsToRemove.length > 0) messageList.removeByIds(idsToRemove);
30850
30958
  if (messagesToSave.length > 0) await this.persistMessages(messagesToSave, threadId, resourceId);
@@ -31631,6 +31739,7 @@ ${formattedMessages}
31631
31739
  threadId,
31632
31740
  resourceId,
31633
31741
  messages: unobservedMessages,
31742
+ messageList: opts.messageList,
31634
31743
  reflectionHooks,
31635
31744
  agent: opts.agent,
31636
31745
  requestContext,
@@ -31911,7 +32020,7 @@ function isTemporalGapMarkerForMessage(message, targetMessageId) {
31911
32020
  async function insertTemporalGapMarkers({ messageList, sendSignal }) {
31912
32021
  const latestInputMessage = messageList.get.input.db().filter((message) => Boolean(message)).at(-1);
31913
32022
  if (!latestInputMessage || isTemporalGapMarker(latestInputMessage)) return;
31914
- const allMessages = messageList.get.all.db().filter((message) => Boolean(message));
32023
+ const allMessages = getObservableMessages(messageList).filter((message) => Boolean(message));
31915
32024
  const latestInputIndex = allMessages.findIndex((message) => message.id === latestInputMessage.id);
31916
32025
  if (latestInputIndex <= 0) return;
31917
32026
  if (allMessages.some((message) => isTemporalGapMarkerForMessage(message, latestInputMessage.id))) return;
@@ -32016,7 +32125,7 @@ var ObservationalMemoryProcessor = class {
32016
32125
  this.temporalMarkers = options?.temporalMarkers ?? false;
32017
32126
  }
32018
32127
  async processInputStep(args) {
32019
- const { messageList, requestContext, stepNumber, state: _state, writer, model, abortSignal, abort, rotateResponseMessageId } = args;
32128
+ const { messageList, requestContext, stepNumber, state: _state, writer, model, abortSignal, abort, messageId, rotateResponseMessageId } = args;
32020
32129
  const state = _state ?? {};
32021
32130
  omDebug(`[OM:processInputStep:ENTER] step=${stepNumber}, hasMastraMemory=${!!requestContext?.get("MastraMemory")}, hasMemoryInfo=${!!messageList?.serialize()?.memoryInfo?.threadId}`);
32022
32131
  const context = this.engine.getThreadContext(requestContext, messageList);
@@ -32102,6 +32211,7 @@ var ObservationalMemoryProcessor = class {
32102
32211
  state.__omObservabilityContext = observabilityContext;
32103
32212
  this.turn.observabilityContext = observabilityContext;
32104
32213
  this.turn.actorModelContext = actorModelContext;
32214
+ this.turn.responseMessageId = messageId;
32105
32215
  {
32106
32216
  const step = this.turn.step(stepNumber);
32107
32217
  let ctx;
@@ -32132,7 +32242,7 @@ var ObservationalMemoryProcessor = class {
32132
32242
  threadId,
32133
32243
  resourceId
32134
32244
  });
32135
- const allDbMsgs = messageList.get.all.db();
32245
+ const allDbMsgs = getObservableMessages(messageList);
32136
32246
  const tokenCounter = this.engine.getTokenCounter();
32137
32247
  const contextTokens = await tokenCounter.countMessagesAsync(allDbMsgs);
32138
32248
  const otherThreadsContext = this.turn.context.otherThreadsContext;
@@ -32479,6 +32589,18 @@ var Memory = class extends _mastra_core_memory.MastraMemory {
32479
32589
  _omEngine;
32480
32590
  _omEngineInstance;
32481
32591
  _mastraInstance;
32592
+ /**
32593
+ * Every vector cleanup that deleteThread or deleteMessages started in the background.
32594
+ * Callers do not wait for the cleanup, so this handle is the only join point.
32595
+ */
32596
+ pendingVectorCleanup = Promise.resolve();
32597
+ /**
32598
+ * Adds a background vector cleanup to the join handle.
32599
+ * The handle keeps the earlier cleanups, so it settles only after all of them end.
32600
+ */
32601
+ trackVectorCleanup(cleanup) {
32602
+ this.pendingVectorCleanup = Promise.allSettled([this.pendingVectorCleanup, cleanup]).then(() => void 0);
32603
+ }
32482
32604
  /** The shared ObservationalMemory engine. Lazily created on first access. */
32483
32605
  get omEngine() {
32484
32606
  if (!this._omEngine) this._omEngine = this._initOMEngine().then((engine) => {
@@ -32743,26 +32865,40 @@ var Memory = class extends _mastra_core_memory.MastraMemory {
32743
32865
  const thread = await memoryStore.getThreadById({ threadId });
32744
32866
  await memoryStore.deleteThread({ threadId });
32745
32867
  if (thread?.resourceId && memoryStore.supportsObservationalMemory) await memoryStore.clearObservationalMemory(threadId, thread.resourceId);
32746
- if (this.vector) this.deleteThreadVectors(threadId);
32868
+ if (this.vector) this.trackVectorCleanup(this.deleteThreadVectors(threadId));
32747
32869
  }
32748
32870
  /**
32749
- * Lists all vector indexes that match the memory messages prefix.
32750
- * Handles separator differences across vector store backends (e.g. '_' vs '-').
32871
+ * Prefix shared by every message index. The index for the default embedding
32872
+ * dimension is named with the bare prefix; other dimensions add a suffix.
32751
32873
  */
32752
- async getMemoryVectorIndexes() {
32874
+ get messageIndexPrefix() {
32875
+ return this.getEmbeddingIndexName();
32876
+ }
32877
+ /**
32878
+ * Prefix shared by every observation index. Each observation index adds a dimension suffix.
32879
+ */
32880
+ get observationIndexPrefix() {
32881
+ return `memory${this.vector?.indexSeparator ?? "_"}observations`;
32882
+ }
32883
+ /**
32884
+ * Lists the vector indexes whose name starts with one of the given prefixes.
32885
+ * Index names can carry a dimension suffix, so discovery matches on the prefix.
32886
+ */
32887
+ async getMemoryVectorIndexes(prefixes) {
32753
32888
  if (!this.vector) return [];
32754
- const prefix = `memory${this.vector.indexSeparator ?? "_"}messages`;
32755
- return (await this.vector.listIndexes()).filter((name) => name.startsWith(prefix));
32889
+ return (await this.vector.listIndexes()).filter((name) => prefixes.some((prefix) => name.startsWith(prefix)));
32756
32890
  }
32757
32891
  /**
32758
32892
  * Deletes all vector embeddings associated with a thread.
32759
32893
  * This is called internally by deleteThread to clean up orphaned vectors.
32894
+ * Both message and observation vectors are removed, so no text of the deleted
32895
+ * thread stays reachable through resource-scoped retrieval.
32760
32896
  *
32761
32897
  * @param threadId - The ID of the thread whose vectors should be deleted
32762
32898
  */
32763
32899
  async deleteThreadVectors(threadId) {
32764
32900
  try {
32765
- const memoryIndexes = await this.getMemoryVectorIndexes();
32901
+ const memoryIndexes = await this.getMemoryVectorIndexes([this.messageIndexPrefix, this.observationIndexPrefix]);
32766
32902
  await Promise.all(memoryIndexes.map(async (indexName) => {
32767
32903
  try {
32768
32904
  await this.vector.deleteVectors({
@@ -32770,14 +32906,14 @@ var Memory = class extends _mastra_core_memory.MastraMemory {
32770
32906
  filter: { thread_id: threadId }
32771
32907
  });
32772
32908
  } catch {
32773
- this.logger.debug("Failed to delete vectors for thread, skipping", {
32909
+ this.logger.warn("Failed to delete vectors of the deleted thread from index", {
32774
32910
  threadId,
32775
32911
  indexName
32776
32912
  });
32777
32913
  }
32778
32914
  }));
32779
32915
  } catch {
32780
- this.logger.debug("Failed to clean up vectors for thread", { threadId });
32916
+ this.logger.warn("Failed to clean up vectors of the deleted thread", { threadId });
32781
32917
  }
32782
32918
  }
32783
32919
  async updateWorkingMemory({ threadId, resourceId, workingMemory, memoryConfig, observabilityContext }) {
@@ -33450,7 +33586,7 @@ Notes:
33450
33586
  getObservationEmbeddingIndexName(dimensions) {
33451
33587
  const usedDimensions = dimensions ?? 384;
33452
33588
  const separator = this.vector?.indexSeparator ?? "_";
33453
- return `memory${separator}observations${separator}${usedDimensions}`;
33589
+ return `${this.observationIndexPrefix}${separator}${usedDimensions}`;
33454
33590
  }
33455
33591
  async createObservationEmbeddingIndex(dimensions) {
33456
33592
  const usedDimensions = dimensions ?? 384;
@@ -33696,7 +33832,10 @@ Notes:
33696
33832
  tools[name] = tool;
33697
33833
  }
33698
33834
  const omConfig = normalizeObservationalMemoryConfig(mergedConfig.observationalMemory);
33699
- if (omConfig?.retrieval) tools.recall = recallTool(mergedConfig, { retrievalScope: typeof omConfig.retrieval === "object" ? omConfig.retrieval.scope ?? "resource" : "resource" });
33835
+ if (omConfig?.retrieval) tools.recall = recallTool(mergedConfig, {
33836
+ retrievalScope: typeof omConfig.retrieval === "object" ? omConfig.retrieval.scope ?? "resource" : "resource",
33837
+ searchEnabled: this.hasRetrievalSearch(omConfig.retrieval)
33838
+ });
33700
33839
  return tools;
33701
33840
  }
33702
33841
  /**
@@ -33752,7 +33891,7 @@ Notes:
33752
33891
  }));
33753
33892
  const messageIdsNeedingDeletion = /* @__PURE__ */ new Set([...messageIdsWithClearedContent, ...messageIdsWithNewEmbeddings]);
33754
33893
  if (messageIdsNeedingDeletion.size > 0) try {
33755
- const memoryIndexes = await this.getMemoryVectorIndexes();
33894
+ const memoryIndexes = await this.getMemoryVectorIndexes([this.messageIndexPrefix]);
33756
33895
  const idsToDelete = [...messageIdsNeedingDeletion];
33757
33896
  await Promise.all(memoryIndexes.map(async (indexName) => {
33758
33897
  for (let i = 0; i < idsToDelete.length; i += VECTOR_DELETE_BATCH_SIZE) {
@@ -33811,7 +33950,7 @@ Notes:
33811
33950
  const span = this.createMemorySpan("delete", observabilityContext, void 0, { messageCount: messageIds.length });
33812
33951
  try {
33813
33952
  await (await this.getMemoryStore()).deleteMessages(messageIds);
33814
- if (this.vector) this.deleteMessageVectors(messageIds);
33953
+ if (this.vector) this.trackVectorCleanup(this.deleteMessageVectors(messageIds));
33815
33954
  span?.end({
33816
33955
  output: { success: true },
33817
33956
  attributes: { messageCount: messageIds.length }
@@ -33827,12 +33966,14 @@ Notes:
33827
33966
  /**
33828
33967
  * Deletes vector embeddings for specific messages.
33829
33968
  * This is called internally by deleteMessages to clean up orphaned vectors.
33969
+ * Only the message indexes are touched, because observation vectors can hold
33970
+ * text of other messages of the thread.
33830
33971
  *
33831
33972
  * @param messageIds - The IDs of the messages whose vectors should be deleted
33832
33973
  */
33833
33974
  async deleteMessageVectors(messageIds) {
33834
33975
  try {
33835
- const memoryIndexes = await this.getMemoryVectorIndexes();
33976
+ const memoryIndexes = await this.getMemoryVectorIndexes([this.messageIndexPrefix]);
33836
33977
  await Promise.all(memoryIndexes.map(async (indexName) => {
33837
33978
  for (let i = 0; i < messageIds.length; i += VECTOR_DELETE_BATCH_SIZE) {
33838
33979
  const batch = messageIds.slice(i, i + VECTOR_DELETE_BATCH_SIZE);
@@ -44608,4 +44749,4 @@ const agentBuilderWorkflows = {
44608
44749
  //#endregion
44609
44750
  exports.agentBuilderWorkflows = agentBuilderWorkflows;
44610
44751
 
44611
- //# sourceMappingURL=dist-COHIL6fR.cjs.map
44752
+ //# sourceMappingURL=dist-C2-SedDQ.cjs.map