@mastra/server 1.59.1-alpha.0 → 1.60.0-alpha.10

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 (185) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/dist/_types/@internal_voice/dist/_types/@internal_core/dist/request-context/index.d.ts +46 -1
  3. package/dist/{a2a-CUkzkdTZ.js → a2a-B5m54dOP.js} +2 -2
  4. package/dist/{a2a-CUkzkdTZ.js.map → a2a-B5m54dOP.js.map} +1 -1
  5. package/dist/{a2a-DzZHH3OH.cjs → a2a-Eeib3vfP.cjs} +2 -2
  6. package/dist/{a2a-DzZHH3OH.cjs.map → a2a-Eeib3vfP.cjs.map} +1 -1
  7. package/dist/{agents-uT8ZDE4k.js → agents-BetrUB_N.js} +7 -2
  8. package/dist/agents-BetrUB_N.js.map +1 -0
  9. package/dist/{agents-0Tw3kkD_.cjs → agents-CLv_RFQx.cjs} +18 -1
  10. package/dist/agents-CLv_RFQx.cjs.map +1 -0
  11. package/dist/{api-schema-manifest-BlxXMFWo.js → api-schema-manifest-BKTXRheC.js} +2 -2
  12. package/dist/{api-schema-manifest-BlxXMFWo.js.map → api-schema-manifest-BKTXRheC.js.map} +1 -1
  13. package/dist/{api-schema-manifest-iAEVS-Re.cjs → api-schema-manifest-BbNdh5Ck.cjs} +2 -2
  14. package/dist/{api-schema-manifest-iAEVS-Re.cjs.map → api-schema-manifest-BbNdh5Ck.cjs.map} +1 -1
  15. package/dist/{builder-registry-B8KyPAOP.js → builder-registry-CqLsr39q.js} +2 -2
  16. package/dist/{builder-registry-B8KyPAOP.js.map → builder-registry-CqLsr39q.js.map} +1 -1
  17. package/dist/{builder-registry-Dcou-kzd.cjs → builder-registry-CyaUg_iP.cjs} +2 -2
  18. package/dist/{builder-registry-Dcou-kzd.cjs.map → builder-registry-CyaUg_iP.cjs.map} +1 -1
  19. package/dist/{channels-B9yt3a2P.js → channels-BnFQESMf.js} +2 -2
  20. package/dist/{channels-B9yt3a2P.js.map → channels-BnFQESMf.js.map} +1 -1
  21. package/dist/{channels-BRoq3VKR.cjs → channels-Dzy6VM3w.cjs} +2 -2
  22. package/dist/{channels-BRoq3VKR.cjs.map → channels-Dzy6VM3w.cjs.map} +1 -1
  23. package/dist/{constants-ChBaIptn.cjs → constants-CXPpy-Ef.cjs} +7 -1
  24. package/dist/constants-CXPpy-Ef.cjs.map +1 -0
  25. package/dist/{constants-Cp1x-6sJ.js → constants-CutMu4A_.js} +7 -1
  26. package/dist/constants-CutMu4A_.js.map +1 -0
  27. package/dist/{dist-RYanMda7.cjs → dist-C2O8fRb-.cjs} +230 -71
  28. package/dist/dist-C2O8fRb-.cjs.map +1 -0
  29. package/dist/{dist-ByXtFaHm.js → dist-DNaReo7-.js} +230 -71
  30. package/dist/dist-DNaReo7-.js.map +1 -0
  31. package/dist/docs/SKILL.md +2 -2
  32. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  33. package/dist/docs/references/{docs-agents-a2a.md → docs-connections-a2a.md} +2 -2
  34. package/dist/docs/references/docs-server-custom-api-routes.md +2 -2
  35. package/dist/{editor-builder-DT7ypWfa.cjs → editor-builder-1L3OIY4K.cjs} +2 -2
  36. package/dist/{editor-builder-DT7ypWfa.cjs.map → editor-builder-1L3OIY4K.cjs.map} +1 -1
  37. package/dist/{editor-builder-DJUxdzC8.js → editor-builder-BDEm-gZe.js} +2 -2
  38. package/dist/{editor-builder-DJUxdzC8.js.map → editor-builder-BDEm-gZe.js.map} +1 -1
  39. package/dist/{editor-builder-C3ZvffGu.cjs → editor-builder-DNRVszU-.cjs} +2 -2
  40. package/dist/{editor-builder-C3ZvffGu.cjs.map → editor-builder-DNRVszU-.cjs.map} +1 -1
  41. package/dist/{editor-builder-Byg6wbi6.js → editor-builder-EP9FAtQm.js} +2 -2
  42. package/dist/{editor-builder-Byg6wbi6.js.map → editor-builder-EP9FAtQm.js.map} +1 -1
  43. package/dist/{helpers-TmTGZi8e.cjs → helpers-C54OMiDG.cjs} +2 -2
  44. package/dist/{helpers-TmTGZi8e.cjs.map → helpers-C54OMiDG.cjs.map} +1 -1
  45. package/dist/{helpers-GyeAi5YN.js → helpers-Da9nPOFL.js} +2 -2
  46. package/dist/{helpers-GyeAi5YN.js.map → helpers-Da9nPOFL.js.map} +1 -1
  47. package/dist/{routes-BpOjCX2F.js → routes-iUe0w9eL.js} +7 -5
  48. package/dist/routes-iUe0w9eL.js.map +1 -0
  49. package/dist/{routes-BBRC9gg2.cjs → routes-mK_LlDMo.cjs} +7 -5
  50. package/dist/routes-mK_LlDMo.cjs.map +1 -0
  51. package/dist/server/auth/index.cjs +2 -2
  52. package/dist/server/auth/index.js +2 -2
  53. package/dist/server/constants.d.ts +5 -0
  54. package/dist/server/constants.d.ts.map +1 -1
  55. package/dist/server/handlers/a2a.cjs +1 -1
  56. package/dist/server/handlers/a2a.js +1 -1
  57. package/dist/server/handlers/agent-builder.cjs +3 -3
  58. package/dist/server/handlers/agent-builder.js +3 -3
  59. package/dist/server/handlers/agent-controller.cjs +41 -14
  60. package/dist/server/handlers/agent-controller.cjs.map +1 -1
  61. package/dist/server/handlers/agent-controller.d.ts +20 -2
  62. package/dist/server/handlers/agent-controller.d.ts.map +1 -1
  63. package/dist/server/handlers/agent-controller.js +41 -14
  64. package/dist/server/handlers/agent-controller.js.map +1 -1
  65. package/dist/server/handlers/agent-versions.cjs +1 -1
  66. package/dist/server/handlers/agent-versions.js +1 -1
  67. package/dist/server/handlers/agents.cjs +6 -5
  68. package/dist/server/handlers/agents.cjs.map +1 -1
  69. package/dist/server/handlers/agents.d.ts.map +1 -1
  70. package/dist/server/handlers/agents.js +6 -5
  71. package/dist/server/handlers/agents.js.map +1 -1
  72. package/dist/server/handlers/auth.cjs +2 -2
  73. package/dist/server/handlers/auth.js +2 -2
  74. package/dist/server/handlers/authorship.cjs +1 -1
  75. package/dist/server/handlers/authorship.js +1 -1
  76. package/dist/server/handlers/builder-registry.cjs +1 -1
  77. package/dist/server/handlers/builder-registry.js +1 -1
  78. package/dist/server/handlers/channels.cjs +1 -1
  79. package/dist/server/handlers/channels.js +1 -1
  80. package/dist/server/handlers/conversations.cjs +1 -1
  81. package/dist/server/handlers/conversations.js +1 -1
  82. package/dist/server/handlers/datasets.cjs +1 -1
  83. package/dist/server/handlers/datasets.js +1 -1
  84. package/dist/server/handlers/editor-builder.cjs +1 -1
  85. package/dist/server/handlers/editor-builder.js +1 -1
  86. package/dist/server/handlers/favorites-enrichment.cjs +1 -1
  87. package/dist/server/handlers/favorites-enrichment.js +1 -1
  88. package/dist/server/handlers/logs.cjs +1 -1
  89. package/dist/server/handlers/logs.js +1 -1
  90. package/dist/server/handlers/mcp-client-versions.cjs +1 -1
  91. package/dist/server/handlers/mcp-client-versions.js +1 -1
  92. package/dist/server/handlers/mcp.cjs.map +1 -1
  93. package/dist/server/handlers/mcp.d.ts +6 -0
  94. package/dist/server/handlers/mcp.d.ts.map +1 -1
  95. package/dist/server/handlers/mcp.js.map +1 -1
  96. package/dist/server/handlers/memory.cjs +1 -1
  97. package/dist/server/handlers/memory.js +1 -1
  98. package/dist/server/handlers/plans.cjs +64 -0
  99. package/dist/server/handlers/plans.cjs.map +1 -0
  100. package/dist/server/handlers/plans.d.ts +43 -0
  101. package/dist/server/handlers/plans.d.ts.map +1 -0
  102. package/dist/server/handlers/plans.js +57 -0
  103. package/dist/server/handlers/plans.js.map +1 -0
  104. package/dist/server/handlers/prompt-block-versions.cjs +1 -1
  105. package/dist/server/handlers/prompt-block-versions.js +1 -1
  106. package/dist/server/handlers/responses.adapter.cjs +1 -1
  107. package/dist/server/handlers/responses.adapter.js +1 -1
  108. package/dist/server/handlers/responses.cjs +1 -1
  109. package/dist/server/handlers/responses.js +1 -1
  110. package/dist/server/handlers/responses.storage.cjs +1 -1
  111. package/dist/server/handlers/responses.storage.js +1 -1
  112. package/dist/server/handlers/scorer-versions.cjs +1 -1
  113. package/dist/server/handlers/scorer-versions.js +1 -1
  114. package/dist/server/handlers/stored-agent-favorites.cjs +2 -2
  115. package/dist/server/handlers/stored-agent-favorites.js +2 -2
  116. package/dist/server/handlers/stored-agents.cjs +2 -2
  117. package/dist/server/handlers/stored-agents.js +2 -2
  118. package/dist/server/handlers/stored-mcp-clients.cjs +1 -1
  119. package/dist/server/handlers/stored-mcp-clients.js +1 -1
  120. package/dist/server/handlers/stored-prompt-blocks.cjs +1 -1
  121. package/dist/server/handlers/stored-prompt-blocks.js +1 -1
  122. package/dist/server/handlers/stored-scorers.cjs +1 -1
  123. package/dist/server/handlers/stored-scorers.js +1 -1
  124. package/dist/server/handlers/stored-skill-favorites.cjs +2 -2
  125. package/dist/server/handlers/stored-skill-favorites.js +2 -2
  126. package/dist/server/handlers/stored-skills.cjs +2 -2
  127. package/dist/server/handlers/stored-skills.js +2 -2
  128. package/dist/server/handlers/stored-workspaces.cjs +1 -1
  129. package/dist/server/handlers/stored-workspaces.js +1 -1
  130. package/dist/server/handlers/system.cjs +1 -1
  131. package/dist/server/handlers/system.js +1 -1
  132. package/dist/server/handlers/tool-providers.cjs +1 -1
  133. package/dist/server/handlers/tool-providers.js +1 -1
  134. package/dist/server/handlers/tool-schema-overrides.cjs +46 -0
  135. package/dist/server/handlers/tool-schema-overrides.cjs.map +1 -0
  136. package/dist/server/handlers/tool-schema-overrides.d.ts +13 -0
  137. package/dist/server/handlers/tool-schema-overrides.d.ts.map +1 -0
  138. package/dist/server/handlers/tool-schema-overrides.js +45 -0
  139. package/dist/server/handlers/tool-schema-overrides.js.map +1 -0
  140. package/dist/server/handlers/tools.cjs +7 -6
  141. package/dist/server/handlers/tools.cjs.map +1 -1
  142. package/dist/server/handlers/tools.d.ts.map +1 -1
  143. package/dist/server/handlers/tools.js +7 -6
  144. package/dist/server/handlers/tools.js.map +1 -1
  145. package/dist/server/handlers/utils.cjs +1 -1
  146. package/dist/server/handlers/utils.js +1 -1
  147. package/dist/server/handlers/validate-agent-instructions.cjs +1 -1
  148. package/dist/server/handlers/validate-agent-instructions.js +1 -1
  149. package/dist/server/handlers/workflows.cjs +3 -3
  150. package/dist/server/handlers/workflows.js +3 -3
  151. package/dist/server/handlers.cjs +8 -1
  152. package/dist/server/handlers.d.ts +1 -0
  153. package/dist/server/handlers.d.ts.map +1 -1
  154. package/dist/server/handlers.js +3 -2
  155. package/dist/server/schemas/agents.d.ts +12 -0
  156. package/dist/server/schemas/agents.d.ts.map +1 -1
  157. package/dist/server/schemas/index.cjs +4 -2
  158. package/dist/server/schemas/index.js +3 -3
  159. package/dist/server/server-adapter/index.cjs +66 -4
  160. package/dist/server/server-adapter/index.cjs.map +1 -1
  161. package/dist/server/server-adapter/index.d.ts +12 -0
  162. package/dist/server/server-adapter/index.d.ts.map +1 -1
  163. package/dist/server/server-adapter/index.js +65 -5
  164. package/dist/server/server-adapter/index.js.map +1 -1
  165. package/dist/server/server-adapter/mcp-auth.d.ts +43 -0
  166. package/dist/server/server-adapter/mcp-auth.d.ts.map +1 -0
  167. package/dist/server/server-adapter/routes/agents.d.ts +2 -0
  168. package/dist/server/server-adapter/routes/agents.d.ts.map +1 -1
  169. package/dist/{utils-Bna_JCkb.cjs → utils-BkPZAGxS.cjs} +2 -2
  170. package/dist/{utils-Bna_JCkb.cjs.map → utils-BkPZAGxS.cjs.map} +1 -1
  171. package/dist/{utils-wTwyTjg3.cjs → utils-CXbhpYYv.cjs} +2 -2
  172. package/dist/{utils-wTwyTjg3.cjs.map → utils-CXbhpYYv.cjs.map} +1 -1
  173. package/dist/{utils-QXKhjIm6.js → utils-CljhO7OY.js} +2 -2
  174. package/dist/{utils-QXKhjIm6.js.map → utils-CljhO7OY.js.map} +1 -1
  175. package/dist/{utils-CmHd1Sgh.js → utils-qMLbyf2U.js} +2 -2
  176. package/dist/{utils-CmHd1Sgh.js.map → utils-qMLbyf2U.js.map} +1 -1
  177. package/package.json +4 -4
  178. package/dist/agents-0Tw3kkD_.cjs.map +0 -1
  179. package/dist/agents-uT8ZDE4k.js.map +0 -1
  180. package/dist/constants-ChBaIptn.cjs.map +0 -1
  181. package/dist/constants-Cp1x-6sJ.js.map +0 -1
  182. package/dist/dist-ByXtFaHm.js.map +0 -1
  183. package/dist/dist-RYanMda7.cjs.map +0 -1
  184. package/dist/routes-BBRC9gg2.cjs.map +0 -1
  185. package/dist/routes-BpOjCX2F.js.map +0 -1
@@ -12,9 +12,9 @@ let _mastra_core_memory = require("@mastra/core/memory");
12
12
  let _mastra_core_agent = require("@mastra/core/agent");
13
13
  let _mastra_core_error = require("@mastra/core/error");
14
14
  let _mastra_core_llm = require("@mastra/core/llm");
15
+ let _mastra_core_tools = require("@mastra/core/tools");
15
16
  let util = require("util");
16
17
  let crypto$1 = require("crypto");
17
- let _mastra_core_tools = require("@mastra/core/tools");
18
18
  let _mastra_core_utils = require("@mastra/core/utils");
19
19
  let _mastra_core_storage = require("@mastra/core/storage");
20
20
  let _mastra_core_features = require("@mastra/core/features");
@@ -4693,7 +4693,7 @@ function splitLines(text) {
4693
4693
  return result;
4694
4694
  }
4695
4695
  //#endregion
4696
- //#region ../memory/dist/src-BYD6Wp5m.js
4696
+ //#region ../memory/dist/src-C-nmWgoF.js
4697
4697
  var __defProp$3 = Object.defineProperty;
4698
4698
  var __exportAll = (all, no_symbols) => {
4699
4699
  let target = {};
@@ -20528,21 +20528,17 @@ Or as a standalone observation when closing out a broader task:
20528
20528
  Completion observations should be terse but specific about WHAT was completed.
20529
20529
  Prefer concrete resolved outcomes over abstract workflow status so the assistant remembers what is already done.`;
20530
20530
  buildObserverOutputFormat();
20531
- function buildObserverOutputFormat(extractors = []) {
20532
- const extractorSections = buildExtractorOutputSections(extractors);
20533
- const legacyContinuationSections = extractors.length === 0 ? `
20534
- <current-task>
20535
- State the current task(s) explicitly:
20536
- - Primary: What the agent is currently working on
20537
- - Secondary: Other pending tasks (mark as "waiting for user" if appropriate)
20538
- </current-task>
20539
-
20540
- <suggested-response>
20541
- Hint for the agent's immediate next message. Examples:
20542
- - "I've updated the navigation model. Let me walk you through the changes..."
20543
- - "The assistant should wait for the user to respond before continuing."
20544
- - Call the view tool on src/example.ts to continue debugging.
20545
- </suggested-response>` : "";
20531
+ /**
20532
+ * Build the Observer's output format.
20533
+ *
20534
+ * `extractors` distinguishes two cases that both look empty:
20535
+ * - `undefined` — the no-arg call behind the exported defaults (OBSERVER_OUTPUT_FORMAT_BASE,
20536
+ * OBSERVER_SYSTEM_PROMPT, REFLECTOR_SYSTEM_PROMPT), which keep describing both built-in
20537
+ * sections with their historical text. Runtime callers always pass the composed list.
20538
+ * - `[]` — the caller composed extractors and every section was disabled, so no continuation
20539
+ * sections are described at all.
20540
+ */
20541
+ function buildObserverOutputFormat(extractors) {
20546
20542
  return `Use priority levels:
20547
20543
  - 🔴 High: explicit user facts, preferences, unresolved goals, critical context
20548
20544
  - 🟡 Medium: project details, learned information, tool results
@@ -20568,7 +20564,19 @@ Date: Dec 5, 2025
20568
20564
  * 🔴 (09:15) Continued work on feature X
20569
20565
  </observations>
20570
20566
 
20571
- ${extractorSections || legacyContinuationSections}`;
20567
+ ${buildExtractorOutputSections(extractors ?? []) || (extractors === void 0 ? `
20568
+ <current-task>
20569
+ State the current task(s) explicitly:
20570
+ - Primary: What the agent is currently working on
20571
+ - Secondary: Other pending tasks (mark as "waiting for user" if appropriate)
20572
+ </current-task>
20573
+
20574
+ <suggested-response>
20575
+ Hint for the agent's immediate next message. Examples:
20576
+ - "I've updated the navigation model. Let me walk you through the changes..."
20577
+ - "The assistant should wait for the user to respond before continuing."
20578
+ - Call the view tool on src/example.ts to continue debugging.
20579
+ </suggested-response>` : "")}`;
20572
20580
  }
20573
20581
  /**
20574
20582
  * The guidelines for the Observer.
@@ -20595,10 +20603,22 @@ const OBSERVER_GUIDELINES = `- Be specific enough for the assistant to act on
20595
20603
  * Build the complete observer system prompt.
20596
20604
  * @param multiThread - Whether this is for multi-thread batched observation (default: false)
20597
20605
  * @param instruction - Optional custom instructions to append to the prompt
20606
+ * @param includeThreadTitle - Whether the Observer should also produce a thread title
20607
+ * @param extractors - Active extractors, used to decide which sections the prompt describes.
20608
+ * Omitted only by the exported no-arg defaults; pass `[]` to describe no continuation sections at all.
20598
20609
  */
20599
- function buildObserverSystemPrompt(multiThread = false, instruction, includeThreadTitle = false, extractors = []) {
20610
+ function buildObserverSystemPrompt(multiThread = false, instruction, includeThreadTitle = false, extractors) {
20600
20611
  const outputFormat = buildObserverOutputFormat(extractors);
20601
- const multiThreadTitleInstruction = includeThreadTitle ? ` Each thread's observations, current-task, suggested-response, and thread-title should be nested inside a <thread id="..."> block within <observations>.` : ` Each thread's observations, current-task, and suggested-response should be nested inside a <thread id="..."> block within <observations>.`;
20612
+ const customInstructions = instruction ? `\n\n=== CUSTOM INSTRUCTIONS ===\n\n${instruction}` : "";
20613
+ const currentTaskEnabled = extractors === void 0 || extractors.some((extractor) => extractor.slug === "current-task");
20614
+ const suggestedResponseEnabled = extractors === void 0 || extractors.some((extractor) => extractor.slug === "suggested-response");
20615
+ const multiThreadSections = [
20616
+ "observations",
20617
+ ...currentTaskEnabled ? ["current-task"] : [],
20618
+ ...suggestedResponseEnabled ? ["suggested-response"] : [],
20619
+ ...includeThreadTitle ? ["thread-title"] : []
20620
+ ];
20621
+ const multiThreadTitleInstruction = ` Each thread's ${multiThreadSections.length <= 2 ? multiThreadSections.join(" and ") : `${multiThreadSections.slice(0, -1).join(", ")}, and ${multiThreadSections[multiThreadSections.length - 1]}`} should be nested inside a <thread id="..."> block within <observations>.`;
20602
20622
  const multiThreadTitleExample = includeThreadTitle ? `
20603
20623
  <thread-title>Feature X implementation</thread-title>` : "";
20604
20624
  const multiThreadSecondTitleExample = includeThreadTitle ? `
@@ -20628,28 +20648,28 @@ For multi-thread output, wrap each thread's observations like this:
20628
20648
  <thread id="thread_id_1">
20629
20649
  Date: Dec 4, 2025
20630
20650
  * 🔴 (14:30) User prefers direct answers
20631
- * 🔴 (14:31) Working on feature X
20651
+ * 🔴 (14:31) Working on feature X${currentTaskEnabled ? `
20632
20652
 
20633
20653
  <current-task>
20634
20654
  What the agent is currently working on in this thread
20635
- </current-task>
20655
+ </current-task>` : ""}${suggestedResponseEnabled ? `
20636
20656
 
20637
20657
  <suggested-response>
20638
20658
  Hint for the agent's next message in this thread
20639
- </suggested-response>${multiThreadTitleExample}
20659
+ </suggested-response>` : ""}${multiThreadTitleExample}
20640
20660
  </thread>
20641
20661
 
20642
20662
  <thread id="thread_id_2">
20643
20663
  Date: Dec 5, 2025
20644
- * 🔴 (09:15) User asked about deployment
20664
+ * 🔴 (09:15) User asked about deployment${currentTaskEnabled ? `
20645
20665
 
20646
20666
  <current-task>
20647
20667
  Current task for this thread
20648
- </current-task>
20668
+ </current-task>` : ""}${suggestedResponseEnabled ? `
20649
20669
 
20650
20670
  <suggested-response>
20651
20671
  Suggested response for this thread
20652
- </suggested-response>${multiThreadSecondTitleExample}
20672
+ </suggested-response>` : ""}${multiThreadSecondTitleExample}
20653
20673
  </thread>
20654
20674
  </observations>
20655
20675
 
@@ -20659,7 +20679,7 @@ ${OBSERVER_GUIDELINES}
20659
20679
 
20660
20680
  Remember: These observations are the assistant's ONLY memory. Make them count.
20661
20681
 
20662
- User messages are extremely important. If the user asks a question or gives a new task, make it clear in <current-task> that this is the priority.${instruction ? `\n\n=== CUSTOM INSTRUCTIONS ===\n\n${instruction}` : ""}`;
20682
+ User messages are extremely important.${currentTaskEnabled ? " If the user asks a question or gives a new task, make it clear in <current-task> that this is the priority." : ""}${customInstructions}`;
20663
20683
  return `You are the memory consciousness of an AI assistant. Your observations will be the ONLY information the assistant has about past interactions with this user.
20664
20684
 
20665
20685
  Extract observations that will help the assistant remember:
@@ -20684,7 +20704,7 @@ Simply output your observations without any thread-related markup.
20684
20704
 
20685
20705
  Remember: These observations are the assistant's ONLY memory. Make them count.
20686
20706
 
20687
- User messages are extremely important. If the user asks a question or gives a new task, make it clear in <current-task> that this is the priority. If the assistant needs to respond to the user, indicate in <suggested-response> that it should pause for user reply before continuing other tasks.${instruction ? `\n\n=== CUSTOM INSTRUCTIONS ===\n\n${instruction}` : ""}`;
20707
+ User messages are extremely important.${currentTaskEnabled ? " If the user asks a question or gives a new task, make it clear in <current-task> that this is the priority." : ""}${suggestedResponseEnabled ? " If the assistant needs to respond to the user, indicate in <suggested-response> that it should pause for user reply before continuing other tasks." : ""}${customInstructions}`;
20688
20708
  }
20689
20709
  /**
20690
20710
  * Observer Agent System Prompt (default - for backwards compatibility)
@@ -21376,7 +21396,7 @@ function optimizeObservationsForContext(observations) {
21376
21396
  let optimized = stripEphemeralAnchorIds(observations);
21377
21397
  optimized = optimized.replace(/🟡\s*/g, "");
21378
21398
  optimized = optimized.replace(/🟢\s*/g, "");
21379
- optimized = optimized.replace(/\[(?![\d\s]*items collapsed)[^\]]+\]/g, "");
21399
+ optimized = optimized.replace(/\[(?![\d\s]*items collapsed)[^\]]+\](?!\()/g, "");
21380
21400
  optimized = optimized.replace(/\s*->\s*/g, " ");
21381
21401
  optimized = optimized.replace(/ +/g, " ");
21382
21402
  optimized = optimized.replace(/\n{3,}/g, "\n\n");
@@ -22786,6 +22806,7 @@ var TokenCounter = class TokenCounter {
22786
22806
  defaultModelContext;
22787
22807
  modelContextStorage = new async_hooks.AsyncLocalStorage();
22788
22808
  inFlightAttachmentCounts = /* @__PURE__ */ new Map();
22809
+ multimodalToolResultCounts = /* @__PURE__ */ new WeakMap();
22789
22810
  static TOKENS_PER_MESSAGE = 3.8;
22790
22811
  static TOKENS_PER_CONVERSATION = 24;
22791
22812
  constructor(options) {
@@ -22848,6 +22869,9 @@ var TokenCounter = class TokenCounter {
22848
22869
  }
22849
22870
  countMultimodalToolResultContent(part, toolResult) {
22850
22871
  if (!toolResult || typeof toolResult !== "object") return;
22872
+ const resultKey = buildEstimateKey("tool-result-multimodal-content-source", JSON.stringify(toolResult));
22873
+ const cached = this.multimodalToolResultCounts.get(part);
22874
+ if (cached?.resultKey === resultKey) return cached.tokens;
22851
22875
  const output = toolResult;
22852
22876
  const content = output.type === "content" && Array.isArray(output.value) ? output.value : output.content;
22853
22877
  if (!Array.isArray(content)) return;
@@ -22959,10 +22983,15 @@ var TokenCounter = class TokenCounter {
22959
22983
  countJsonContentPart(contentPart);
22960
22984
  }
22961
22985
  if (!hasAttachment) return;
22962
- return this.readOrPersistFixedPartEstimate(part, "tool-result-multimodal-content", JSON.stringify({
22986
+ const estimate = this.readOrPersistFixedPartEstimate(part, "tool-result-multimodal-content", JSON.stringify({
22963
22987
  type: "content",
22964
22988
  value: cacheParts
22965
22989
  }), tokens);
22990
+ this.multimodalToolResultCounts.set(part, {
22991
+ resultKey,
22992
+ tokens: estimate
22993
+ });
22994
+ return estimate;
22966
22995
  }
22967
22996
  estimateImageAssetTokens(part, asset, kind) {
22968
22997
  const modelContext = this.getModelContext();
@@ -24436,21 +24465,22 @@ const SET_WORKING_MEMORY_TOOL_NAME = "setWorkingMemory";
24436
24465
  /**
24437
24466
  * Deep merges two objects, with special handling for null values (delete) and arrays (replace).
24438
24467
  * - Object properties are recursively merged
24439
- * - null values in the update will delete the corresponding property
24468
+ * - null values in the update will delete the corresponding property, even when the property
24469
+ * or its parent object does not exist yet (so padded nulls never get stored literally)
24440
24470
  * - Arrays are replaced entirely (not merged element-by-element)
24441
24471
  * - Primitive values are overwritten
24472
+ * - The returned object is always newly constructed and never aliases `update`
24442
24473
  */
24443
24474
  function deepMergeWorkingMemory(existing, update) {
24444
24475
  if (!update || typeof update !== "object" || Object.keys(update).length === 0) return existing && typeof existing === "object" ? { ...existing } : {};
24445
- if (!existing || typeof existing !== "object") return update;
24446
- const result = { ...existing };
24476
+ const result = { ...existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {} };
24447
24477
  for (const key of Object.keys(update)) {
24448
24478
  const updateValue = update[key];
24449
24479
  const existingValue = result[key];
24450
24480
  if (updateValue === void 0) continue;
24451
24481
  if (updateValue === null) delete result[key];
24452
24482
  else if (Array.isArray(updateValue)) result[key] = updateValue;
24453
- else if (typeof updateValue === "object" && updateValue !== null && typeof existingValue === "object" && existingValue !== null && !Array.isArray(existingValue)) result[key] = deepMergeWorkingMemory(existingValue, updateValue);
24483
+ else if (typeof updateValue === "object") result[key] = deepMergeWorkingMemory(existingValue && typeof existingValue === "object" && !Array.isArray(existingValue) ? existingValue : void 0, updateValue);
24454
24484
  else result[key] = updateValue;
24455
24485
  }
24456
24486
  return result;
@@ -24931,23 +24961,43 @@ function createThreadTitleExtractor() {
24931
24961
  metadataKeyPath: "threadTitle"
24932
24962
  }, true);
24933
24963
  }
24964
+ /**
24965
+ * Normalize the user-facing `continuationHints` config into explicit per-section flags.
24966
+ * Both sections stay enabled unless the caller opts out, so omitting the config is a no-op.
24967
+ */
24968
+ function resolveContinuationHints(config) {
24969
+ if (config === void 0 || config === true) return {
24970
+ currentTask: true,
24971
+ suggestedResponse: true
24972
+ };
24973
+ if (config === false) return {
24974
+ currentTask: false,
24975
+ suggestedResponse: false
24976
+ };
24977
+ return {
24978
+ currentTask: config.currentTask ?? true,
24979
+ suggestedResponse: config.suggestedResponse ?? true
24980
+ };
24981
+ }
24934
24982
  function composeExtractors(options) {
24983
+ const continuationHints = resolveContinuationHints(options.continuationHints);
24935
24984
  const extractors = [];
24936
- if (options.includeContinuationHints) extractors.push(createCurrentTaskExtractor(), createSuggestedResponseExtractor());
24985
+ if (continuationHints.currentTask) extractors.push(createCurrentTaskExtractor());
24986
+ if (continuationHints.suggestedResponse) extractors.push(createSuggestedResponseExtractor());
24937
24987
  if (options.includeThreadTitle) extractors.push(createThreadTitleExtractor());
24938
24988
  extractors.push(...options.userExtractors ?? []);
24939
24989
  return validateExtractorList(extractors);
24940
24990
  }
24941
24991
  function composeObservationExtractors(config) {
24942
24992
  return composeExtractors({
24943
- includeContinuationHints: true,
24993
+ continuationHints: config.continuationHints,
24944
24994
  includeThreadTitle: config.threadTitle,
24945
24995
  userExtractors: config.extract
24946
24996
  });
24947
24997
  }
24948
24998
  function composeReflectionExtractors(config) {
24949
24999
  return composeExtractors({
24950
- includeContinuationHints: true,
25000
+ continuationHints: config.continuationHints,
24951
25001
  userExtractors: config.extract
24952
25002
  });
24953
25003
  }
@@ -26708,10 +26758,12 @@ var ObservationStep = class {
26708
26758
  resourceId,
26709
26759
  checkThreshold: true,
26710
26760
  messages: step0Messages,
26761
+ record: this.turn.record,
26711
26762
  currentModel: this.turn.actorModelContext,
26712
26763
  writer: this.turn.writer,
26713
26764
  messageList
26714
26765
  });
26766
+ this.turn.setRecord(activation.record);
26715
26767
  if (activation.activated) {
26716
26768
  activated = true;
26717
26769
  if (activation.activatedMessageIds?.length) messageList.removeByIds(activation.activatedMessageIds);
@@ -26753,6 +26805,7 @@ var ObservationStep = class {
26753
26805
  let statusSnapshot = await om.getStatus({
26754
26806
  threadId,
26755
26807
  resourceId,
26808
+ record: this.turn.record,
26756
26809
  messages: getObservableMessages(messageList)
26757
26810
  });
26758
26811
  if (statusSnapshot.shouldBuffer && !hasIncompleteToolCalls) {
@@ -26770,7 +26823,7 @@ var ObservationStep = class {
26770
26823
  messageList.removeByIds(candidates.map((msg) => msg.id));
26771
26824
  for (const msg of candidates) messageList.add(msg, "memory");
26772
26825
  }
26773
- om.buffer({
26826
+ om.trackBackgroundWork(om.buffer({
26774
26827
  threadId,
26775
26828
  resourceId,
26776
26829
  messages: unobservedMessages,
@@ -26781,7 +26834,7 @@ var ObservationStep = class {
26781
26834
  observabilityContext: this.turn.observabilityContext
26782
26835
  }).catch((err) => {
26783
26836
  omDebug(`[OM:buffer] fire-and-forget buffer failed: ${err?.message}`);
26784
- });
26837
+ }));
26785
26838
  buffered = true;
26786
26839
  }
26787
26840
  const willObserveNow = statusSnapshot.shouldObserve && !hasIncompleteToolCalls;
@@ -26848,6 +26901,7 @@ var ObservationStep = class {
26848
26901
  statusSnapshot = await om.getStatus({
26849
26902
  threadId,
26850
26903
  resourceId,
26904
+ record: this.turn.record,
26851
26905
  messages: getObservableMessages(messageList)
26852
26906
  });
26853
26907
  }
@@ -26898,10 +26952,12 @@ var ObservationStep = class {
26898
26952
  const { threadId, resourceId, messageList } = this.turn;
26899
26953
  const om = this.turn.om;
26900
26954
  await om.waitForBuffering(threadId, resourceId);
26955
+ await this.turn.refreshRecord();
26901
26956
  const observableMessages = this.seededResponseMessage ? getObservableMessages(messageList).filter((msg) => msg.id !== this.turn.responseMessageId) : getObservableMessages(messageList);
26902
26957
  const freshStatus = await om.getStatus({
26903
26958
  threadId,
26904
26959
  resourceId,
26960
+ record: this.turn.record,
26905
26961
  messages: observableMessages
26906
26962
  });
26907
26963
  if (!freshStatus.shouldObserve) return {
@@ -26912,11 +26968,13 @@ var ObservationStep = class {
26912
26968
  const activation = await om.activate({
26913
26969
  threadId,
26914
26970
  resourceId,
26971
+ record: this.turn.record,
26915
26972
  messages: observableMessages,
26916
26973
  currentModel: this.turn.actorModelContext,
26917
26974
  writer: this.turn.writer,
26918
26975
  messageList
26919
26976
  });
26977
+ this.turn.setRecord(activation.record);
26920
26978
  if (activation.activated) {
26921
26979
  const postActivationRecord = activation.record;
26922
26980
  await om.reflector.maybeReflect({
@@ -27099,6 +27157,18 @@ var ObservationTurn = class {
27099
27157
  };
27100
27158
  return this._context;
27101
27159
  }
27160
+ /** Replace the cached turn record with a specific instance. */
27161
+ setRecord(record) {
27162
+ this._record = record;
27163
+ if (this._context) this._context.record = record;
27164
+ }
27165
+ /** Patch the cached turn record with merged fields. */
27166
+ patchRecord(patch) {
27167
+ this.setRecord({
27168
+ ...this.record,
27169
+ ...patch
27170
+ });
27171
+ }
27102
27172
  /**
27103
27173
  * Create a step handle. If a previous step exists, it is finalized
27104
27174
  * (its output messages will be saved at the start of the new step's prepare()).
@@ -27130,7 +27200,7 @@ var ObservationTurn = class {
27130
27200
  const allMessages = getObservableMessages(this.messageList);
27131
27201
  const record = this._record;
27132
27202
  const unobservedMessages = this.om.getUnobservedMessages(allMessages, record);
27133
- if (unobservedMessages.length > 0) this.om.buffer({
27203
+ if (unobservedMessages.length > 0) this.om.trackBackgroundWork(this.om.buffer({
27134
27204
  threadId: this.threadId,
27135
27205
  resourceId: this.resourceId,
27136
27206
  messages: unobservedMessages,
@@ -27144,7 +27214,7 @@ var ObservationTurn = class {
27144
27214
  skipMinimumTokenCheck: true
27145
27215
  }).catch((err) => {
27146
27216
  omDebug(`[OM:turn.end] idle buffer failed: ${err?.message}`);
27147
- });
27217
+ }));
27148
27218
  }
27149
27219
  return { record: this._record };
27150
27220
  }
@@ -27153,7 +27223,7 @@ var ObservationTurn = class {
27153
27223
  * @internal
27154
27224
  */
27155
27225
  async refreshRecord() {
27156
- this._record = await this.om.getOrCreateRecord(this.threadId, this.resourceId);
27226
+ this.setRecord(await this.om.getOrCreateRecord(this.threadId, this.resourceId));
27157
27227
  }
27158
27228
  /**
27159
27229
  * Refresh cross-thread context for resource scope. Called per-step.
@@ -27206,9 +27276,13 @@ var ObservationTurn = class {
27206
27276
  * - Preserving ALL important information (reflections become the ENTIRE memory)
27207
27277
  *
27208
27278
  * @param instruction - Optional custom instructions to append to the prompt
27279
+ * @param extractors - Active extractors, used to decide which sections the prompt describes
27209
27280
  */
27210
- function buildReflectorSystemPrompt(instruction, extractors = []) {
27281
+ function buildReflectorSystemPrompt(instruction, extractors) {
27211
27282
  const outputFormat = buildObserverOutputFormat(extractors);
27283
+ const customInstructions = instruction ? `\n\n=== CUSTOM INSTRUCTIONS ===\n\n${instruction}` : "";
27284
+ const currentTaskEnabled = extractors === void 0 || extractors.some((extractor) => extractor.slug === "current-task");
27285
+ const suggestedResponseEnabled = extractors === void 0 || extractors.some((extractor) => extractor.slug === "suggested-response");
27212
27286
  return `You are the memory consciousness of an AI assistant. Your memory observation reflections will be the ONLY information the assistant has about past interactions with this user.
27213
27287
 
27214
27288
  The following instructions were given to another part of your psyche (the observer) to create memories.
@@ -27285,7 +27359,7 @@ Date: Dec 4, 2025
27285
27359
 
27286
27360
  ${outputFormat}
27287
27361
 
27288
- User messages are extremely important. If the user asks a question or gives a new task, make it clear in <current-task> that this is the priority. If the assistant needs to respond to the user, indicate in <suggested-response> that it should pause for user reply before continuing other tasks.${instruction ? `\n\n=== CUSTOM INSTRUCTIONS ===\n\n${instruction}` : ""}`;
27362
+ User messages are extremely important.${currentTaskEnabled ? " If the user asks a question or gives a new task, make it clear in <current-task> that this is the priority." : ""}${suggestedResponseEnabled ? " If the assistant needs to respond to the user, indicate in <suggested-response> that it should pause for user reply before continuing other tasks." : ""}${customInstructions}`;
27289
27363
  }
27290
27364
  buildReflectorSystemPrompt();
27291
27365
  /**
@@ -27620,6 +27694,8 @@ var ReflectorRunner = class {
27620
27694
  };
27621
27695
  let reflectedTokens = 0;
27622
27696
  let attemptNumber = 0;
27697
+ /** Observations from the previous attempt, used to detect a no-progress ladder. */
27698
+ let previousObservations;
27623
27699
  while (currentLevel <= maxLevel) {
27624
27700
  attemptNumber++;
27625
27701
  const isRetry = attemptNumber > 1;
@@ -27693,6 +27769,11 @@ var ReflectorRunner = class {
27693
27769
  omDebug(`[OM:callReflector] degenerate output persists at maxLevel=${maxLevel}, breaking`);
27694
27770
  break;
27695
27771
  }
27772
+ if (!parsed.degenerate && previousObservations !== void 0 && parsed.observations === previousObservations) {
27773
+ omDebug(`[OM:callReflector] attempt #${attemptNumber} returned output identical to the previous attempt; escalating cannot help, stopping the ladder`);
27774
+ break;
27775
+ }
27776
+ previousObservations = parsed.observations;
27696
27777
  if (streamContext?.writer) {
27697
27778
  const failedMarker = createObservationFailedMarker({
27698
27779
  cycleId: streamContext.cycleId,
@@ -28667,6 +28748,39 @@ var ObservationalMemory = class ObservationalMemory {
28667
28748
  */
28668
28749
  recordInitializations = /* @__PURE__ */ new Map();
28669
28750
  /**
28751
+ * In-flight fire-and-forget background cycles (buffered observation, reflection).
28752
+ * Tracked so callers can join them via `settled()` before closing a storage
28753
+ * connection they own — otherwise a background cycle's tail statements race the close.
28754
+ */
28755
+ pendingBackgroundWork = /* @__PURE__ */ new Set();
28756
+ /**
28757
+ * Register fire-and-forget background work so `settled()` can join it.
28758
+ * Returns the original promise so callers keep their own rejection handling.
28759
+ */
28760
+ trackBackgroundWork(work) {
28761
+ const tracked = work.catch(() => {}).finally(() => {
28762
+ this.pendingBackgroundWork.delete(tracked);
28763
+ });
28764
+ this.pendingBackgroundWork.add(tracked);
28765
+ return work;
28766
+ }
28767
+ /**
28768
+ * Resolve once all background observational-memory work started so far has finished.
28769
+ *
28770
+ * Background cycles enqueue further background work (a buffered observation can
28771
+ * trigger a reflection, which runs nested agent streams), so this drains repeatedly
28772
+ * until nothing is left rather than joining a single snapshot.
28773
+ */
28774
+ async settled() {
28775
+ const maxDrainRounds = 100;
28776
+ for (let round = 0; round < maxDrainRounds; round++) {
28777
+ if (this.pendingBackgroundWork.size === 0) return;
28778
+ await Promise.allSettled([...this.pendingBackgroundWork]);
28779
+ }
28780
+ if (this.pendingBackgroundWork.size === 0) return;
28781
+ omError(`[OM:settled] background work still pending after ${maxDrainRounds} drain rounds; giving up waiting`);
28782
+ }
28783
+ /**
28670
28784
  * Acquire a lock for the given key, execute the callback, then release.
28671
28785
  * If a lock is already held, waits for it to be released before acquiring.
28672
28786
  */
@@ -28743,7 +28857,8 @@ var ObservationalMemory = class ObservationalMemory {
28743
28857
  observeAttachments: config.observation?.observeAttachments ?? true,
28744
28858
  extractors: composeObservationExtractors({
28745
28859
  threadTitle: config.observation?.threadTitle ?? false,
28746
- extract: config.observation?.extract
28860
+ extract: config.observation?.extract,
28861
+ continuationHints: config.observation?.continuationHints
28747
28862
  })
28748
28863
  };
28749
28864
  this.reflectionConfig = {
@@ -28760,7 +28875,10 @@ var ObservationalMemory = class ObservationalMemory {
28760
28875
  activateOnProviderChange: config.reflection?.activateOnProviderChange ?? false,
28761
28876
  blockAfter: asyncBufferingDisabled ? void 0 : resolveBlockAfter(config.reflection?.blockAfter ?? (config.reflection?.bufferActivation ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.bufferActivation ? 1.2 : void 0), config.reflection?.observationTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.observationTokens),
28762
28877
  instruction: config.reflection?.instruction,
28763
- extractors: composeReflectionExtractors({ extract: config.reflection?.extract })
28878
+ extractors: composeReflectionExtractors({
28879
+ extract: config.reflection?.extract,
28880
+ continuationHints: config.reflection?.continuationHints
28881
+ })
28764
28882
  };
28765
28883
  this.tokenCounter = new TokenCounter({ model: typeof observationModel === "string" ? observationModel : void 0 });
28766
28884
  this.onDebugEvent = config.onDebugEvent;
@@ -29663,7 +29781,7 @@ ${formattedMessages}
29663
29781
  if (!this.buffering.isAsyncObservationEnabled()) return false;
29664
29782
  const lockKey = this.buffering.getLockKey(opts.threadId, opts.resourceId);
29665
29783
  const shouldTrigger = this.buffering.shouldTriggerAsyncObservation(opts.pendingTokens, lockKey, opts.record, this.storage, opts.threshold);
29666
- if (shouldTrigger) this.startAsyncBufferedObservation(opts.record, opts.threadId, opts.unobservedMessages, lockKey, opts.writer, opts.unbufferedPendingTokens, opts.requestContext);
29784
+ if (shouldTrigger) this.trackBackgroundWork(this.startAsyncBufferedObservation(opts.record, opts.threadId, opts.unobservedMessages, lockKey, opts.writer, opts.unbufferedPendingTokens, opts.requestContext));
29667
29785
  return shouldTrigger;
29668
29786
  }
29669
29787
  isMessageList(value) {
@@ -29875,8 +29993,9 @@ ${formattedMessages}
29875
29993
  return;
29876
29994
  }
29877
29995
  const omMetadata = (0, _mastra_core_memory.getThreadOMMetadata)((await this.storage.getThreadById({ threadId }))?.metadata);
29878
- const currentTask = omMetadata?.currentTask;
29879
- const suggestedResponse = omMetadata?.suggestedResponse;
29996
+ const activeExtractors = [...this.observationConfig.extractors, ...this.reflectionConfig.extractors];
29997
+ const currentTask = activeExtractors.some((extractor) => extractor.slug === "current-task") ? omMetadata?.currentTask : void 0;
29998
+ const suggestedResponse = activeExtractors.some((extractor) => extractor.slug === "suggested-response") ? omMetadata?.suggestedResponse : void 0;
29880
29999
  const currentDate = opts.currentDate ?? /* @__PURE__ */ new Date();
29881
30000
  return this.formatObservationsForContext(record.activeObservations, currentTask, suggestedResponse, omMetadata?.extracted, unobservedContextBlocks, currentDate, this.retrieval);
29882
30001
  }
@@ -29975,7 +30094,10 @@ ${formattedMessages}
29975
30094
  }
29976
30095
  };
29977
30096
  omDebug(`[OM:status] step=${stepNumber} msgs=${pendingTokens}/${threshold} obs=${currentObservationTokens}/${effectiveObservationTokensThreshold} gen=${record.generationCount}`);
29978
- await writer.custom(statusPart).catch(() => {});
30097
+ await writer.custom({
30098
+ ...statusPart,
30099
+ transient: true
30100
+ }).catch(() => {});
29979
30101
  }
29980
30102
  }
29981
30103
  /**
@@ -30001,11 +30123,11 @@ ${formattedMessages}
30001
30123
  * ```
30002
30124
  */
30003
30125
  async getStatus(opts) {
30004
- const { threadId, resourceId } = opts;
30005
- const record = await this.getOrCreateRecord(threadId, resourceId);
30126
+ const { threadId, resourceId, record: providedRecord, messages } = opts;
30127
+ const record = providedRecord ?? await this.getOrCreateRecord(threadId, resourceId);
30006
30128
  const currentObservationTokens = record.observationTokenCount ?? 0;
30007
30129
  let unobservedMessages;
30008
- if (opts.messages) unobservedMessages = this.getUnobservedMessages(opts.messages, record);
30130
+ if (messages) unobservedMessages = this.getUnobservedMessages(messages, record);
30009
30131
  else {
30010
30132
  const rawMessages = await this.loadMessagesFromStorage(threadId, resourceId, record.lastObservedAt ? new Date(record.lastObservedAt) : void 0);
30011
30133
  unobservedMessages = this.getUnobservedMessages(rawMessages, record);
@@ -30162,6 +30284,7 @@ ${formattedMessages}
30162
30284
  async buffer(opts) {
30163
30285
  const { threadId, resourceId, requestContext, observabilityContext } = opts;
30164
30286
  let record = opts.record ?? await this.getOrCreateRecord(threadId, resourceId);
30287
+ const inMemoryRecord = record;
30165
30288
  if (!this.buffering.isAsyncObservationEnabled()) return {
30166
30289
  buffered: false,
30167
30290
  record
@@ -30180,6 +30303,8 @@ ${formattedMessages}
30180
30303
  await existingOp;
30181
30304
  } catch {}
30182
30305
  registerOp(record.id, "bufferingObservation");
30306
+ inMemoryRecord.isBufferingObservation = true;
30307
+ inMemoryRecord.lastBufferedAtTokens = currentTokens;
30183
30308
  this.storage.setBufferingObservationFlag(record.id, true, currentTokens).catch((err) => {
30184
30309
  omError("[OM] Failed to set buffering observation flag", err);
30185
30310
  });
@@ -30189,6 +30314,14 @@ ${formattedMessages}
30189
30314
  });
30190
30315
  BufferingCoordinator.asyncBufferingOps.set(bufferKey, opPromise);
30191
30316
  record = await this.storage.getObservationalMemory(record.threadId, record.resourceId) ?? record;
30317
+ const setBufferingState = (isBufferingObservation, lastBufferedAtTokens) => {
30318
+ inMemoryRecord.isBufferingObservation = isBufferingObservation;
30319
+ record.isBufferingObservation = isBufferingObservation;
30320
+ if (lastBufferedAtTokens !== void 0) {
30321
+ inMemoryRecord.lastBufferedAtTokens = lastBufferedAtTokens;
30322
+ record.lastBufferedAtTokens = lastBufferedAtTokens;
30323
+ }
30324
+ };
30192
30325
  let flagCleared = false;
30193
30326
  try {
30194
30327
  let candidateMessages;
@@ -30210,10 +30343,13 @@ ${formattedMessages}
30210
30343
  }
30211
30344
  const minNewTokens = (this.observationConfig.bufferTokens ?? 5e3) / 2;
30212
30345
  const newTokens = await this.tokenCounter.countMessagesAsync(candidateMessages);
30213
- if (candidateMessages.length === 0 || !opts.skipMinimumTokenCheck && newTokens < minNewTokens) return {
30214
- buffered: false,
30215
- record
30216
- };
30346
+ if (candidateMessages.length === 0 || !opts.skipMinimumTokenCheck && newTokens < minNewTokens) {
30347
+ setBufferingState(false);
30348
+ return {
30349
+ buffered: false,
30350
+ record
30351
+ };
30352
+ }
30217
30353
  if (opts.beforeBuffer) await opts.beforeBuffer(candidateMessages);
30218
30354
  else if (opts.messages) this.sealMessagesForBuffering(candidateMessages);
30219
30355
  const cycleId = `buffer-obs-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
@@ -30268,13 +30404,14 @@ ${formattedMessages}
30268
30404
  });
30269
30405
  await this.storage.setBufferingObservationFlag(record.id, false, newTokens).catch(() => {});
30270
30406
  flagCleared = true;
30407
+ setBufferingState(false, newTokens);
30271
30408
  BufferingCoordinator.lastBufferedBoundary.set(bufferKey, newTokens);
30272
30409
  const maxTimestamp = this.getMaxMessageTimestamp(candidateMessages);
30273
30410
  const cursor = new Date(maxTimestamp.getTime() + 1);
30274
30411
  BufferingCoordinator.lastBufferedAtTime.set(bufferKey, cursor);
30275
30412
  return {
30276
30413
  buffered: true,
30277
- record: await this.getOrCreateRecord(threadId, resourceId)
30414
+ record: await this.storage.getObservationalMemory(record.threadId, record.resourceId) ?? record
30278
30415
  };
30279
30416
  } catch (error) {
30280
30417
  omError("[OM] buffer() failed", error);
@@ -30286,7 +30423,10 @@ ${formattedMessages}
30286
30423
  unregisterOp(record.id, "bufferingObservation");
30287
30424
  BufferingCoordinator.asyncBufferingOps.delete(bufferKey);
30288
30425
  resolveOp();
30289
- if (!flagCleared) await this.storage.setBufferingObservationFlag(record.id, false).catch(() => {});
30426
+ if (!flagCleared) {
30427
+ setBufferingState(false);
30428
+ await this.storage.setBufferingObservationFlag(record.id, false).catch(() => {});
30429
+ }
30290
30430
  }
30291
30431
  }
30292
30432
  /**
@@ -30312,7 +30452,7 @@ ${formattedMessages}
30312
30452
  /** @internal Used by ObservationStep. */
30313
30453
  async activate(opts) {
30314
30454
  const { threadId, resourceId } = opts;
30315
- const record = await this.getOrCreateRecord(threadId, resourceId);
30455
+ const record = opts.record ?? await this.getOrCreateRecord(threadId, resourceId);
30316
30456
  if (this.buffering.isAsyncObservationEnabled()) {
30317
30457
  const lockKey = this.buffering.getLockKey(threadId, resourceId);
30318
30458
  const bufKey = this.buffering.getObservationBufferKey(lockKey);
@@ -30358,6 +30498,7 @@ ${formattedMessages}
30358
30498
  const status = await this.getStatus({
30359
30499
  threadId,
30360
30500
  resourceId,
30501
+ record,
30361
30502
  messages: thresholdMessages
30362
30503
  });
30363
30504
  if (status.pendingTokens < status.threshold) return {
@@ -31073,31 +31214,30 @@ var ObservationalMemoryProcessor = class {
31073
31214
  threadId,
31074
31215
  resourceId
31075
31216
  });
31076
- const freshRecord = await this.engine.getOrCreateRecord(threadId, resourceId);
31217
+ const turnRecord = this.turn.record;
31077
31218
  await this.engine.emitProgress({
31078
- record: freshRecord,
31219
+ record: turnRecord,
31079
31220
  stepNumber,
31080
31221
  pendingTokens: ctx.status.pendingTokens,
31081
31222
  threshold: ctx.status.threshold,
31082
31223
  effectiveObservationTokensThreshold: ctx.status.effectiveObservationTokensThreshold,
31083
- currentObservationTokens: freshRecord.observationTokenCount ?? 0,
31224
+ currentObservationTokens: turnRecord.observationTokenCount ?? 0,
31084
31225
  writer,
31085
31226
  threadId,
31086
31227
  resourceId
31087
31228
  });
31088
- const allDbMsgs = getObservableMessages(messageList);
31089
- const tokenCounter = this.engine.getTokenCounter();
31090
- const contextTokens = await tokenCounter.countMessagesAsync(allDbMsgs);
31091
- const otherThreadsContext = this.turn.context.otherThreadsContext;
31092
- const finalTotalPending = contextTokens + (otherThreadsContext ? tokenCounter.countString(otherThreadsContext) : 0);
31093
- await this.engine.getStorage().setPendingMessageTokens(freshRecord.id, finalTotalPending).catch(() => {});
31229
+ const finalTotalPending = ctx.status.pendingTokens;
31230
+ try {
31231
+ await this.engine.getStorage().setPendingMessageTokens(turnRecord.id, finalTotalPending);
31232
+ this.turn.patchRecord({ pendingMessageTokens: finalTotalPending });
31233
+ } catch {}
31094
31234
  if (reproCaptureEnabled) writeProcessInputStepReproCapture({
31095
31235
  threadId,
31096
31236
  resourceId,
31097
31237
  stepNumber,
31098
31238
  args,
31099
31239
  preRecord: preRecordSnapshot,
31100
- postRecord: safeCaptureJson(freshRecord),
31240
+ postRecord: safeCaptureJson(turnRecord),
31101
31241
  preMessages: preMessagesSnapshot,
31102
31242
  preBufferedChunks: [],
31103
31243
  preContextTokenCount: 0,
@@ -31444,6 +31584,25 @@ var Memory = class extends _mastra_core_memory.MastraMemory {
31444
31584
  trackVectorCleanup(cleanup) {
31445
31585
  this.pendingVectorCleanup = Promise.allSettled([this.pendingVectorCleanup, cleanup]).then(() => void 0);
31446
31586
  }
31587
+ /**
31588
+ * Resolve once all background work this Memory started has finished: observational-memory
31589
+ * cycles (buffered observation and reflection, including the nested agent runs they spawn)
31590
+ * and vector cleanup from `deleteThread` / `deleteMessages`.
31591
+ *
31592
+ * Callers that own the storage connection should await this before closing it, otherwise
31593
+ * background statements can race the close.
31594
+ *
31595
+ * ```ts
31596
+ * await agent.generate('hello', { memory: { thread, resource } });
31597
+ * await memory.settled();
31598
+ * await store.close();
31599
+ * ```
31600
+ */
31601
+ async settled() {
31602
+ await this.pendingVectorCleanup;
31603
+ await (this._omEngine ? await this._omEngine : this._omEngineInstance)?.settled();
31604
+ await this.pendingVectorCleanup;
31605
+ }
31447
31606
  /** The shared ObservationalMemory engine. Lazily created on first access. */
31448
31607
  get omEngine() {
31449
31608
  if (!this._omEngine) this._omEngine = this._initOMEngine().then((engine) => {
@@ -43590,4 +43749,4 @@ const agentBuilderWorkflows = {
43590
43749
  //#endregion
43591
43750
  exports.agentBuilderWorkflows = agentBuilderWorkflows;
43592
43751
 
43593
- //# sourceMappingURL=dist-RYanMda7.cjs.map
43752
+ //# sourceMappingURL=dist-C2O8fRb-.cjs.map