@mastra/server 1.60.0-alpha.8 → 1.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (294) hide show
  1. package/CHANGELOG.md +140 -0
  2. package/dist/{a2a-Eeib3vfP.cjs → a2a-BtXFFv-0.cjs} +4 -4
  3. package/dist/{a2a-Eeib3vfP.cjs.map → a2a-BtXFFv-0.cjs.map} +1 -1
  4. package/dist/{a2a-B5m54dOP.js → a2a-DZhtQeFL.js} +3 -3
  5. package/dist/{a2a-B5m54dOP.js.map → a2a-DZhtQeFL.js.map} +1 -1
  6. package/dist/{agent-versions-xeysPGel.cjs → agent-versions-MYjO6Wl1.cjs} +2 -2
  7. package/dist/{agent-versions-xeysPGel.cjs.map → agent-versions-MYjO6Wl1.cjs.map} +1 -1
  8. package/dist/{agent-versions-CWEnD62A.js → agent-versions-mFXaw5ma.js} +2 -2
  9. package/dist/{agent-versions-CWEnD62A.js.map → agent-versions-mFXaw5ma.js.map} +1 -1
  10. package/dist/{api-schema-manifest-BKTXRheC.js → api-schema-manifest-Bx_zU5qw.js} +2 -2
  11. package/dist/{api-schema-manifest-BKTXRheC.js.map → api-schema-manifest-Bx_zU5qw.js.map} +1 -1
  12. package/dist/{api-schema-manifest-BbNdh5Ck.cjs → api-schema-manifest-DPgfugJT.cjs} +4 -3
  13. package/dist/{api-schema-manifest-BbNdh5Ck.cjs.map → api-schema-manifest-DPgfugJT.cjs.map} +1 -1
  14. package/dist/{background-tasks-C5G2jJax.cjs → background-tasks-8M9W_27g.cjs} +2 -2
  15. package/dist/{background-tasks-C5G2jJax.cjs.map → background-tasks-8M9W_27g.cjs.map} +1 -1
  16. package/dist/{builder-registry-CyaUg_iP.cjs → builder-registry-Dcd_ApmT.cjs} +3 -3
  17. package/dist/{builder-registry-CyaUg_iP.cjs.map → builder-registry-Dcd_ApmT.cjs.map} +1 -1
  18. package/dist/{builder-registry-CqLsr39q.js → builder-registry-DnEa4qnF.js} +2 -2
  19. package/dist/{builder-registry-CqLsr39q.js.map → builder-registry-DnEa4qnF.js.map} +1 -1
  20. package/dist/{channels-BnFQESMf.js → channels-BO3Zd38V.js} +2 -2
  21. package/dist/{channels-BnFQESMf.js.map → channels-BO3Zd38V.js.map} +1 -1
  22. package/dist/{channels-Dzy6VM3w.cjs → channels-D9WRnKzU.cjs} +3 -3
  23. package/dist/{channels-Dzy6VM3w.cjs.map → channels-D9WRnKzU.cjs.map} +1 -1
  24. package/dist/{constants-CutMu4A_.js → constants-0jFCWoex.js} +13 -2
  25. package/dist/constants-0jFCWoex.js.map +1 -0
  26. package/dist/{constants-CXPpy-Ef.cjs → constants-4IJp_uzj.cjs} +18 -1
  27. package/dist/constants-4IJp_uzj.cjs.map +1 -0
  28. package/dist/{conversations-CcFLCCeF.cjs → conversations-PF0eKhIu.cjs} +3 -3
  29. package/dist/{conversations-CcFLCCeF.cjs.map → conversations-PF0eKhIu.cjs.map} +1 -1
  30. package/dist/{dist-CAVC0nWG.cjs → dist-2zVeGGHi.cjs} +3 -2
  31. package/dist/{dist-CAVC0nWG.cjs.map → dist-2zVeGGHi.cjs.map} +1 -1
  32. package/dist/{dist-D7GkGue6.cjs → dist-8-Z5v77M.cjs} +3 -2
  33. package/dist/{dist-D7GkGue6.cjs.map → dist-8-Z5v77M.cjs.map} +1 -1
  34. package/dist/{dist-SKhVwZMV.cjs → dist-Be7Caz3Z.cjs} +3 -2
  35. package/dist/{dist-SKhVwZMV.cjs.map → dist-Be7Caz3Z.cjs.map} +1 -1
  36. package/dist/{dist-18h28zlO.cjs → dist-BfVTO0pC.cjs} +3 -2
  37. package/dist/{dist-18h28zlO.cjs.map → dist-BfVTO0pC.cjs.map} +1 -1
  38. package/dist/{dist-BD0I5lxM.js → dist-CHJcZQdS.js} +2 -2
  39. package/dist/{dist-BD0I5lxM.js.map → dist-CHJcZQdS.js.map} +1 -1
  40. package/dist/{dist-BpRGQqjE.cjs → dist-CJKQBH69.cjs} +2 -2
  41. package/dist/{dist-BpRGQqjE.cjs.map → dist-CJKQBH69.cjs.map} +1 -1
  42. package/dist/{dist-sUhxlnJz.js → dist-CRgxcDTg.js} +2 -2
  43. package/dist/{dist-sUhxlnJz.js.map → dist-CRgxcDTg.js.map} +1 -1
  44. package/dist/{dist-JdnTASYe.js → dist-CscF1cF8.js} +2 -2
  45. package/dist/{dist-JdnTASYe.js.map → dist-CscF1cF8.js.map} +1 -1
  46. package/dist/{dist-CpxQhZED.js → dist-Cw-T1gX6.js} +2818 -309
  47. package/dist/dist-Cw-T1gX6.js.map +1 -0
  48. package/dist/{dist-DBP9kw_8.cjs → dist-D4NzuG3G.cjs} +3 -2
  49. package/dist/{dist-DBP9kw_8.cjs.map → dist-D4NzuG3G.cjs.map} +1 -1
  50. package/dist/{dist-CpaK1qK1.cjs → dist-DERatX43.cjs} +2819 -310
  51. package/dist/dist-DERatX43.cjs.map +1 -0
  52. package/dist/{dist-mcwHCl2a.js → dist-F_Ql1co6.js} +2 -2
  53. package/dist/{dist-mcwHCl2a.js.map → dist-F_Ql1co6.js.map} +1 -1
  54. package/dist/{dist-C-9xUY65.js → dist-Jn3uXsoB.js} +2 -2
  55. package/dist/{dist-C-9xUY65.js.map → dist-Jn3uXsoB.js.map} +1 -1
  56. package/dist/{dist-DyBO3IVt.js → dist-bAFqx06T.js} +2 -2
  57. package/dist/{dist-DyBO3IVt.js.map → dist-bAFqx06T.js.map} +1 -1
  58. package/dist/docs/SKILL.md +1 -1
  59. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  60. package/dist/{dynamic-workflows-C-6vmau5.cjs → dynamic-workflows-BZ5ru36x.cjs} +3 -3
  61. package/dist/{dynamic-workflows-C-6vmau5.cjs.map → dynamic-workflows-BZ5ru36x.cjs.map} +1 -1
  62. package/dist/{dynamic-workflows-B0TE8mjA.js → dynamic-workflows-C6U0Rdoc.js} +2 -2
  63. package/dist/{dynamic-workflows-B0TE8mjA.js.map → dynamic-workflows-C6U0Rdoc.js.map} +1 -1
  64. package/dist/{editor-builder-1L3OIY4K.cjs → editor-builder-BmRQift0.cjs} +2 -2
  65. package/dist/{editor-builder-1L3OIY4K.cjs.map → editor-builder-BmRQift0.cjs.map} +1 -1
  66. package/dist/{helpers-C54OMiDG.cjs → helpers-BWxRRShz.cjs} +2 -2
  67. package/dist/{helpers-C54OMiDG.cjs.map → helpers-BWxRRShz.cjs.map} +1 -1
  68. package/dist/{helpers-Da9nPOFL.js → helpers-DBAYsA50.js} +2 -2
  69. package/dist/{helpers-Da9nPOFL.js.map → helpers-DBAYsA50.js.map} +1 -1
  70. package/dist/index.cjs +1 -0
  71. package/dist/index.cjs.map +1 -1
  72. package/dist/{observability-new-endpoints-BC-dasRY.cjs → observability-new-endpoints-gRCFhnRr.cjs} +2 -2
  73. package/dist/{observability-new-endpoints-BC-dasRY.cjs.map → observability-new-endpoints-gRCFhnRr.cjs.map} +1 -1
  74. package/dist/{probe-image-size-C2F59z8Z.cjs → probe-image-size-CDCRrXNo.cjs} +140 -33
  75. package/dist/probe-image-size-CDCRrXNo.cjs.map +1 -0
  76. package/dist/{probe-image-size-mXCWYNrz.js → probe-image-size-Tf8sNZhU.js} +137 -33
  77. package/dist/probe-image-size-Tf8sNZhU.js.map +1 -0
  78. package/dist/{responses-BI25doe1.cjs → responses-CKNdSRkS.cjs} +2 -2
  79. package/dist/{responses-BI25doe1.cjs.map → responses-CKNdSRkS.cjs.map} +1 -1
  80. package/dist/{rolldown-runtime-CVvi-lCc.cjs → rolldown-runtime-Bd6kNlEP.cjs} +21 -0
  81. package/dist/{rolldown-runtime-DuvcJU0W.js → rolldown-runtime-maW3aOIk.js} +10 -1
  82. package/dist/{route-builder-BAAedfru.cjs → route-builder-CWsok5ci.cjs} +2 -2
  83. package/dist/{route-builder-BAAedfru.cjs.map → route-builder-CWsok5ci.cjs.map} +1 -1
  84. package/dist/{routes-iUe0w9eL.js → routes-Bh2p-WqG.js} +5 -5
  85. package/dist/{routes-iUe0w9eL.js.map → routes-Bh2p-WqG.js.map} +1 -1
  86. package/dist/{routes-mK_LlDMo.cjs → routes-CdbboDwv.cjs} +10 -10
  87. package/dist/{routes-mK_LlDMo.cjs.map → routes-CdbboDwv.cjs.map} +1 -1
  88. package/dist/{schedules-DOK225ZZ.cjs → schedules-7YUg_TRM.cjs} +2 -2
  89. package/dist/{schedules-DOK225ZZ.cjs.map → schedules-7YUg_TRM.cjs.map} +1 -1
  90. package/dist/{schema-Bv9OdW1f-CHHI-NTr.cjs → schema-Bv9OdW1f-CxTiW8RD.cjs} +2 -2
  91. package/dist/{schema-Bv9OdW1f-CHHI-NTr.cjs.map → schema-Bv9OdW1f-CxTiW8RD.cjs.map} +1 -1
  92. package/dist/schema-CNKnRmv1.cjs +1 -0
  93. package/dist/{scorer-versions-CdVjOtQO.js → scorer-versions-D0_KP67E.js} +2 -2
  94. package/dist/{scorer-versions-CdVjOtQO.js.map → scorer-versions-D0_KP67E.js.map} +1 -1
  95. package/dist/{scorer-versions-CYXtxMTU.cjs → scorer-versions-mL--H4LL.cjs} +2 -2
  96. package/dist/{scorer-versions-CYXtxMTU.cjs.map → scorer-versions-mL--H4LL.cjs.map} +1 -1
  97. package/dist/server/a2a/store.cjs +1 -0
  98. package/dist/server/a2a/store.cjs.map +1 -1
  99. package/dist/server/auth/index.cjs +3 -2
  100. package/dist/server/auth/index.js +2 -2
  101. package/dist/server/browser-stream/index.cjs +1 -0
  102. package/dist/server/browser-stream/index.cjs.map +1 -1
  103. package/dist/server/constants.d.ts +11 -0
  104. package/dist/server/constants.d.ts.map +1 -1
  105. package/dist/server/handlers/a2a.cjs +2 -1
  106. package/dist/server/handlers/a2a.js +1 -1
  107. package/dist/server/handlers/agent-builder.cjs +4 -4
  108. package/dist/server/handlers/agent-builder.js +3 -3
  109. package/dist/server/handlers/agent-controller.cjs +53 -36
  110. package/dist/server/handlers/agent-controller.cjs.map +1 -1
  111. package/dist/server/handlers/agent-controller.d.ts +22 -2
  112. package/dist/server/handlers/agent-controller.d.ts.map +1 -1
  113. package/dist/server/handlers/agent-controller.js +51 -35
  114. package/dist/server/handlers/agent-controller.js.map +1 -1
  115. package/dist/server/handlers/agent-versions.cjs +4 -3
  116. package/dist/server/handlers/agent-versions.cjs.map +1 -1
  117. package/dist/server/handlers/agent-versions.js +2 -2
  118. package/dist/server/handlers/agents.cjs +8 -8
  119. package/dist/server/handlers/agents.d.ts +8 -0
  120. package/dist/server/handlers/agents.d.ts.map +1 -1
  121. package/dist/server/handlers/agents.js +5 -5
  122. package/dist/server/handlers/auth.cjs +16 -7
  123. package/dist/server/handlers/auth.cjs.map +1 -1
  124. package/dist/server/handlers/auth.d.ts +10 -4
  125. package/dist/server/handlers/auth.d.ts.map +1 -1
  126. package/dist/server/handlers/auth.js +14 -6
  127. package/dist/server/handlers/auth.js.map +1 -1
  128. package/dist/server/handlers/author-enrichment.cjs +1 -0
  129. package/dist/server/handlers/author-enrichment.cjs.map +1 -1
  130. package/dist/server/handlers/authorship.cjs +2 -1
  131. package/dist/server/handlers/authorship.cjs.map +1 -1
  132. package/dist/server/handlers/authorship.js +1 -1
  133. package/dist/server/handlers/background-tasks.cjs +2 -1
  134. package/dist/server/handlers/builder-registry.cjs +2 -1
  135. package/dist/server/handlers/builder-registry.js +1 -1
  136. package/dist/server/handlers/channels.cjs +2 -1
  137. package/dist/server/handlers/channels.js +1 -1
  138. package/dist/server/handlers/conversations.cjs +4 -4
  139. package/dist/server/handlers/conversations.js +2 -2
  140. package/dist/server/handlers/datasets.cjs +3 -2
  141. package/dist/server/handlers/datasets.cjs.map +1 -1
  142. package/dist/server/handlers/datasets.d.ts +6 -6
  143. package/dist/server/handlers/datasets.js +1 -1
  144. package/dist/server/handlers/dynamic-workflows.cjs +2 -1
  145. package/dist/server/handlers/dynamic-workflows.js +1 -1
  146. package/dist/server/handlers/editor-builder.cjs +2 -1
  147. package/dist/server/handlers/error.cjs +1 -0
  148. package/dist/server/handlers/error.cjs.map +1 -1
  149. package/dist/server/handlers/favorites-enrichment.cjs +2 -1
  150. package/dist/server/handlers/favorites-enrichment.cjs.map +1 -1
  151. package/dist/server/handlers/gateway-memory-client.cjs +1 -0
  152. package/dist/server/handlers/gateway-memory-client.cjs.map +1 -1
  153. package/dist/server/handlers/logs.cjs +3 -3
  154. package/dist/server/handlers/logs.js +2 -2
  155. package/dist/server/handlers/mcp-client-versions.cjs +3 -2
  156. package/dist/server/handlers/mcp-client-versions.cjs.map +1 -1
  157. package/dist/server/handlers/mcp-client-versions.js +1 -1
  158. package/dist/server/handlers/mcp.cjs +2 -2
  159. package/dist/server/handlers/mcp.js +1 -1
  160. package/dist/server/handlers/memory.cjs +3 -3
  161. package/dist/server/handlers/memory.js +2 -2
  162. package/dist/server/handlers/observability-list-query-schemas.cjs +1 -0
  163. package/dist/server/handlers/observability-list-query-schemas.cjs.map +1 -1
  164. package/dist/server/handlers/observability-new-endpoints.cjs +2 -1
  165. package/dist/server/handlers/observability-shared.cjs +2 -1
  166. package/dist/server/handlers/observability-shared.cjs.map +1 -1
  167. package/dist/server/handlers/observability-storage-schemas.cjs +1 -1
  168. package/dist/server/handlers/observability.cjs +8 -5
  169. package/dist/server/handlers/observability.cjs.map +1 -1
  170. package/dist/server/handlers/observability.d.ts.map +1 -1
  171. package/dist/server/handlers/observability.js +7 -4
  172. package/dist/server/handlers/observability.js.map +1 -1
  173. package/dist/server/handlers/plans.cjs +3 -3
  174. package/dist/server/handlers/plans.js +2 -2
  175. package/dist/server/handlers/processor-providers.cjs +2 -1
  176. package/dist/server/handlers/processor-providers.cjs.map +1 -1
  177. package/dist/server/handlers/processors.cjs +2 -1
  178. package/dist/server/handlers/processors.cjs.map +1 -1
  179. package/dist/server/handlers/prompt-block-versions.cjs +3 -2
  180. package/dist/server/handlers/prompt-block-versions.cjs.map +1 -1
  181. package/dist/server/handlers/prompt-block-versions.js +1 -1
  182. package/dist/server/handlers/responses.adapter.cjs +1 -0
  183. package/dist/server/handlers/responses.adapter.cjs.map +1 -1
  184. package/dist/server/handlers/responses.cjs +4 -4
  185. package/dist/server/handlers/responses.js +2 -2
  186. package/dist/server/handlers/responses.storage.cjs +2 -1
  187. package/dist/server/handlers/responses.storage.cjs.map +1 -1
  188. package/dist/server/handlers/responses.storage.js +1 -1
  189. package/dist/server/handlers/schedules-workflows-shim.cjs +1 -1
  190. package/dist/server/handlers/schedules.cjs +2 -1
  191. package/dist/server/handlers/scorer-versions.cjs +4 -3
  192. package/dist/server/handlers/scorer-versions.cjs.map +1 -1
  193. package/dist/server/handlers/scorer-versions.js +2 -2
  194. package/dist/server/handlers/scores.cjs +2 -2
  195. package/dist/server/handlers/scores.js +1 -1
  196. package/dist/server/handlers/skills-sh-shared.cjs +1 -0
  197. package/dist/server/handlers/skills-sh-shared.cjs.map +1 -1
  198. package/dist/server/handlers/stored-agent-favorites.cjs +5 -4
  199. package/dist/server/handlers/stored-agent-favorites.cjs.map +1 -1
  200. package/dist/server/handlers/stored-agent-favorites.js +2 -2
  201. package/dist/server/handlers/stored-agents.cjs +7 -5
  202. package/dist/server/handlers/stored-agents.cjs.map +1 -1
  203. package/dist/server/handlers/stored-agents.d.ts +32 -0
  204. package/dist/server/handlers/stored-agents.d.ts.map +1 -1
  205. package/dist/server/handlers/stored-agents.js +4 -3
  206. package/dist/server/handlers/stored-agents.js.map +1 -1
  207. package/dist/server/handlers/stored-mcp-clients.cjs +3 -2
  208. package/dist/server/handlers/stored-mcp-clients.cjs.map +1 -1
  209. package/dist/server/handlers/stored-mcp-clients.js +1 -1
  210. package/dist/server/handlers/stored-prompt-blocks.cjs +3 -2
  211. package/dist/server/handlers/stored-prompt-blocks.cjs.map +1 -1
  212. package/dist/server/handlers/stored-prompt-blocks.js +1 -1
  213. package/dist/server/handlers/stored-scorers.cjs +4 -3
  214. package/dist/server/handlers/stored-scorers.cjs.map +1 -1
  215. package/dist/server/handlers/stored-scorers.js +2 -2
  216. package/dist/server/handlers/stored-skill-favorites.cjs +4 -3
  217. package/dist/server/handlers/stored-skill-favorites.cjs.map +1 -1
  218. package/dist/server/handlers/stored-skill-favorites.js +1 -1
  219. package/dist/server/handlers/stored-skills.cjs +4 -3
  220. package/dist/server/handlers/stored-skills.cjs.map +1 -1
  221. package/dist/server/handlers/stored-skills.js +1 -1
  222. package/dist/server/handlers/stored-workspaces.cjs +3 -2
  223. package/dist/server/handlers/stored-workspaces.cjs.map +1 -1
  224. package/dist/server/handlers/stored-workspaces.js +1 -1
  225. package/dist/server/handlers/system.cjs +3 -2
  226. package/dist/server/handlers/system.cjs.map +1 -1
  227. package/dist/server/handlers/system.js +1 -1
  228. package/dist/server/handlers/test-utils.cjs +1 -0
  229. package/dist/server/handlers/test-utils.cjs.map +1 -1
  230. package/dist/server/handlers/tool-providers.cjs +3 -2
  231. package/dist/server/handlers/tool-providers.cjs.map +1 -1
  232. package/dist/server/handlers/tool-providers.js +1 -1
  233. package/dist/server/handlers/tool-schema-overrides.cjs +1 -0
  234. package/dist/server/handlers/tool-schema-overrides.cjs.map +1 -1
  235. package/dist/server/handlers/tools.cjs +6 -6
  236. package/dist/server/handlers/tools.js +3 -3
  237. package/dist/server/handlers/utils.cjs +2 -1
  238. package/dist/server/handlers/utils.js +1 -1
  239. package/dist/server/handlers/validate-agent-instructions.cjs +2 -1
  240. package/dist/server/handlers/validate-agent-instructions.cjs.map +1 -1
  241. package/dist/server/handlers/validate-agent-instructions.js +1 -1
  242. package/dist/server/handlers/validate-avatar.cjs +1 -0
  243. package/dist/server/handlers/validate-avatar.cjs.map +1 -1
  244. package/dist/server/handlers/vector.cjs +2 -2
  245. package/dist/server/handlers/vector.js +1 -1
  246. package/dist/server/handlers/version-helpers.cjs +1 -0
  247. package/dist/server/handlers/version-helpers.cjs.map +1 -1
  248. package/dist/server/handlers/voice.cjs +1 -1
  249. package/dist/server/handlers/voice.js +1 -1
  250. package/dist/server/handlers/workflows.cjs +4 -4
  251. package/dist/server/handlers/workflows.js +3 -3
  252. package/dist/server/handlers/workspace.cjs +2 -2
  253. package/dist/server/handlers/workspace.js +1 -1
  254. package/dist/server/handlers.cjs +3 -2
  255. package/dist/server/handlers.js +2 -2
  256. package/dist/server/schemas/datasets.d.ts +3 -3
  257. package/dist/server/schemas/index.cjs +7 -6
  258. package/dist/server/schemas/index.js +4 -4
  259. package/dist/server/schemas/stored-agents.d.ts +40 -7
  260. package/dist/server/schemas/stored-agents.d.ts.map +1 -1
  261. package/dist/server/server-adapter/index.cjs +6 -5
  262. package/dist/server/server-adapter/index.cjs.map +1 -1
  263. package/dist/server/server-adapter/index.js +4 -4
  264. package/dist/server/server-adapter/routes/datasets.d.ts +6 -6
  265. package/dist/{stored-agents-CPxfYRH9.cjs → stored-agents-D6JEb3zN.cjs} +15 -3
  266. package/dist/stored-agents-D6JEb3zN.cjs.map +1 -0
  267. package/dist/{stored-agents-BRBZM-Xl.js → stored-agents-DMW5wrF7.js} +15 -3
  268. package/dist/stored-agents-DMW5wrF7.js.map +1 -0
  269. package/dist/{stored-scorers-B__LF0Cy.js → stored-scorers-BA4suzgn.js} +2 -2
  270. package/dist/{stored-scorers-B__LF0Cy.js.map → stored-scorers-BA4suzgn.js.map} +1 -1
  271. package/dist/{stored-scorers-Cml7jPJv.cjs → stored-scorers-D8IwVM0S.cjs} +2 -2
  272. package/dist/{stored-scorers-Cml7jPJv.cjs.map → stored-scorers-D8IwVM0S.cjs.map} +1 -1
  273. package/dist/{sync-djJ8Lmds.js → sync-BG15Yae1.js} +22 -22
  274. package/dist/{sync-djJ8Lmds.js.map → sync-BG15Yae1.js.map} +1 -1
  275. package/dist/{sync-BHatXKfg.cjs → sync-C4LbbSKR.cjs} +22 -22
  276. package/dist/{sync-BHatXKfg.cjs.map → sync-C4LbbSKR.cjs.map} +1 -1
  277. package/dist/{utils-CljhO7OY.js → utils-B2vd77Fi.js} +2 -2
  278. package/dist/{utils-CljhO7OY.js.map → utils-B2vd77Fi.js.map} +1 -1
  279. package/dist/{utils-BkPZAGxS.cjs → utils-CmYnjLcY.cjs} +4 -4
  280. package/dist/{utils-BkPZAGxS.cjs.map → utils-CmYnjLcY.cjs.map} +1 -1
  281. package/dist/{utils-CXbhpYYv.cjs → utils-DJMUhfvY.cjs} +3 -3
  282. package/dist/{utils-CXbhpYYv.cjs.map → utils-DJMUhfvY.cjs.map} +1 -1
  283. package/dist/{utils-qMLbyf2U.js → utils-Hz8Hc2cd.js} +2 -2
  284. package/dist/{utils-qMLbyf2U.js.map → utils-Hz8Hc2cd.js.map} +1 -1
  285. package/package.json +8 -8
  286. package/dist/constants-CXPpy-Ef.cjs.map +0 -1
  287. package/dist/constants-CutMu4A_.js.map +0 -1
  288. package/dist/dist-CpaK1qK1.cjs.map +0 -1
  289. package/dist/dist-CpxQhZED.js.map +0 -1
  290. package/dist/probe-image-size-C2F59z8Z.cjs.map +0 -1
  291. package/dist/probe-image-size-mXCWYNrz.js.map +0 -1
  292. package/dist/schema-DkBbires.cjs +0 -1
  293. package/dist/stored-agents-BRBZM-Xl.js.map +0 -1
  294. package/dist/stored-agents-CPxfYRH9.cjs.map +0 -1
@@ -1,8 +1,8 @@
1
- import { i as __toESM$1, t as __commonJSMin$1 } from "./rolldown-runtime-DuvcJU0W.js";
1
+ import { o as __toESM$1, t as __commonJSMin$1 } from "./rolldown-runtime-maW3aOIk.js";
2
2
  import { n as standardSchemaToJSONSchema, r as toStandardSchema$1, t as isStandardSchemaWithJSON$1 } from "./schema-Bv9OdW1f-DLSJSqQv.js";
3
3
  import "./schema-CGeYTFwm.js";
4
- import { t as require_sync } from "./sync-djJ8Lmds.js";
5
- import { openai } from "./dist-DyBO3IVt.js";
4
+ import { t as require_sync } from "./sync-BG15Yae1.js";
5
+ import { openai } from "./dist-bAFqx06T.js";
6
6
  import { createRequire } from "module";
7
7
  import * as z4 from "zod/v4";
8
8
  import { z } from "zod/v4";
@@ -17,19 +17,19 @@ import { createTool } from "@mastra/core/tools";
17
17
  import { inspect, promisify } from "util";
18
18
  import { createHash, randomBytes, randomUUID } from "crypto";
19
19
  import { generateEmptyFromSchema } from "@mastra/core/utils";
20
- import { InMemoryStore } from "@mastra/core/storage";
20
+ import { InMemoryStore, assertKnowledgeScopeWithinCeiling, canonicalizeKnowledgeScope, createKnowledgeNodeCursor, expandKnowledgeScope, isKnowledgeScopeVisible, knowledgeScopeKey } from "@mastra/core/storage";
21
21
  import { coreFeatures } from "@mastra/core/features";
22
22
  import { EntityType, SpanType, createObservabilityContext, getOrCreateSpan } from "@mastra/core/observability";
23
23
  import { MASTRA_THREAD_ID_KEY, RequestContext } from "@mastra/core/request-context";
24
24
  import { MessageHistory } from "@mastra/core/processors";
25
25
  import { createStep, createWorkflow } from "@mastra/core/workflows";
26
26
  import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
27
+ import { tmpdir } from "os";
27
28
  import { basename, dirname, extname, isAbsolute, join, relative, resolve } from "path";
28
29
  import { channel, tracingChannel } from "diagnostics_channel";
29
30
  import { AsyncLocalStorage } from "async_hooks";
30
31
  import { exec, execFile, spawn } from "child_process";
31
32
  import { copyFile, mkdir, mkdtemp, readFile, readdir, rm, stat, writeFile } from "fs/promises";
32
- import { tmpdir } from "os";
33
33
  //#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/async-mutex/0.5.0/4b32f2ae13cd0d7acb694455f7c2810d59202098580506b1730c21c7ab02798f/node_modules/async-mutex/index.mjs
34
34
  const E_CANCELED = /* @__PURE__ */ new Error("request for lock canceled");
35
35
  var __awaiter$2 = function(thisArg, _arguments, P, generator) {
@@ -4693,7 +4693,7 @@ function splitLines(text) {
4693
4693
  return result;
4694
4694
  }
4695
4695
  //#endregion
4696
- //#region ../memory/dist/src-BKRU-0Fx.js
4696
+ //#region ../memory/dist/src-aTfbkxBl.js
4697
4697
  var __defProp$3 = Object.defineProperty;
4698
4698
  var __exportAll = (all, no_symbols) => {
4699
4699
  let target = {};
@@ -19240,6 +19240,2388 @@ createIdGenerator$3({
19240
19240
  prefix: "aiobj",
19241
19241
  size: 24
19242
19242
  });
19243
+ const BUILT_IN_SLUGS = /* @__PURE__ */ new Set([
19244
+ "current-task",
19245
+ "suggested-response",
19246
+ "thread-title"
19247
+ ]);
19248
+ const EXTRACTED_VALUES_TAG = "extracted-values";
19249
+ const RESERVED_XML_TAGS = /* @__PURE__ */ new Set([
19250
+ "observations",
19251
+ "observation",
19252
+ EXTRACTED_VALUES_TAG,
19253
+ "thread",
19254
+ "message",
19255
+ "messages",
19256
+ "conversation",
19257
+ "history",
19258
+ "system",
19259
+ "user",
19260
+ "assistant",
19261
+ "tool",
19262
+ ...BUILT_IN_SLUGS
19263
+ ]);
19264
+ const BUILT_IN_EXTRACTOR_SLUGS = [...BUILT_IN_SLUGS];
19265
+ function isBuiltInExtractorSlug(slug) {
19266
+ return BUILT_IN_SLUGS.has(slug);
19267
+ }
19268
+ function slugifyExtractorName(name) {
19269
+ let normalized = "";
19270
+ let previousWasSeparator = false;
19271
+ for (const char of name.trim().toLowerCase()) {
19272
+ const code = char.charCodeAt(0);
19273
+ if (code >= 97 && code <= 122 || code >= 48 && code <= 57) {
19274
+ normalized += char;
19275
+ previousWasSeparator = false;
19276
+ continue;
19277
+ }
19278
+ if (char === "'" || char === "\"" || char === "`") continue;
19279
+ if (!previousWasSeparator && normalized.length > 0) {
19280
+ normalized += "-";
19281
+ previousWasSeparator = true;
19282
+ }
19283
+ }
19284
+ return normalized.endsWith("-") ? normalized.slice(0, -1) : normalized;
19285
+ }
19286
+ function assertValidSlug(slug, name) {
19287
+ if (!slug) throw new Error(`Extractor name "${name}" must produce a non-empty slug.`);
19288
+ const first = slug.charCodeAt(0);
19289
+ const last = slug.charCodeAt(slug.length - 1);
19290
+ const startsWithLetter = first >= 97 && first <= 122;
19291
+ const endsWithLetterOrNumber = last >= 97 && last <= 122 || last >= 48 && last <= 57;
19292
+ const hasOnlySlugCharacters = [...slug].every((char) => {
19293
+ const code = char.charCodeAt(0);
19294
+ return code >= 97 && code <= 122 || code >= 48 && code <= 57 || char === "-";
19295
+ });
19296
+ if (!startsWithLetter || !endsWithLetterOrNumber || !hasOnlySlugCharacters) throw new Error(`Extractor name "${name}" produced invalid slug "${slug}".`);
19297
+ }
19298
+ var Extractor = class Extractor {
19299
+ name;
19300
+ slug;
19301
+ instructions;
19302
+ schema;
19303
+ mode;
19304
+ includePreviousExtraction;
19305
+ metadataKeyPath;
19306
+ onExtracted;
19307
+ retryStructuredExtractionOnEmptyObject;
19308
+ /** @internal */
19309
+ internal;
19310
+ instructionsConfig;
19311
+ schemaConfig;
19312
+ constructor(config, internal = false) {
19313
+ const name = config.name.trim();
19314
+ const instructions = typeof config.instructions === "string" ? config.instructions.trim() : void 0;
19315
+ const slug = slugifyExtractorName(name);
19316
+ const isHook = config.mode === "hook";
19317
+ if (!name) throw new Error("Extractor name is required.");
19318
+ if (!isHook && !config.instructions) throw new Error(`Extractor "${name}" must include instructions.`);
19319
+ if (instructions !== void 0 && !instructions) throw new Error(`Extractor "${name}" must include instructions.`);
19320
+ if (isHook && !config.onExtracted) throw new Error(`Hook extractor "${name}" must include an onExtracted handler.`);
19321
+ if (isHook && (config.instructions || config.schema)) throw new Error(`Hook extractor "${name}" cannot include instructions or a schema.`);
19322
+ assertValidSlug(slug, name);
19323
+ if (!internal && RESERVED_XML_TAGS.has(slug)) throw new Error(`Extractor slug "${slug}" is reserved by Observational Memory.`);
19324
+ this.name = name;
19325
+ this.slug = slug;
19326
+ this.instructionsConfig = config.instructions ?? "";
19327
+ this.schemaConfig = config.schema;
19328
+ this.instructions = instructions ?? "";
19329
+ this.schema = isHook ? z$2.unknown() : typeof config.schema === "function" ? z$2.string() : config.schema ?? z$2.string();
19330
+ this.mode = isHook ? "hook" : internal || !config.schema ? "inline" : "structured";
19331
+ this.includePreviousExtraction = isHook ? false : config.includePreviousExtraction ?? true;
19332
+ this.metadataKeyPath = isHook ? false : config.metadataKeyPath ?? `extracted.${slug}`;
19333
+ this.onExtracted = config.onExtracted;
19334
+ this.retryStructuredExtractionOnEmptyObject = config.retryStructuredExtractionOnEmptyObject ?? false;
19335
+ this.internal = internal;
19336
+ }
19337
+ async resolve(context) {
19338
+ if (this.mode === "hook") return this;
19339
+ const instructions = typeof this.instructionsConfig === "function" ? (await this.instructionsConfig(context)).trim() : this.instructionsConfig.trim();
19340
+ if (!instructions) throw new Error(`Extractor "${this.name}" must include instructions.`);
19341
+ const schema = typeof this.schemaConfig === "function" ? await this.schemaConfig(context) : this.schemaConfig;
19342
+ return new Extractor({
19343
+ name: this.name,
19344
+ instructions,
19345
+ ...schema ? { schema } : {},
19346
+ includePreviousExtraction: this.includePreviousExtraction,
19347
+ metadataKeyPath: this.metadataKeyPath,
19348
+ onExtracted: this.onExtracted,
19349
+ retryStructuredExtractionOnEmptyObject: this.retryStructuredExtractionOnEmptyObject
19350
+ }, this.internal);
19351
+ }
19352
+ };
19353
+ async function resolveExtractors(extractors, context) {
19354
+ return Promise.all(extractors.map((extractor) => extractor.resolve(context)));
19355
+ }
19356
+ function validateExtractorList(extractors) {
19357
+ const seen = /* @__PURE__ */ new Map();
19358
+ for (const extractor of extractors) {
19359
+ assertValidSlug(extractor.slug, extractor.name);
19360
+ if (!extractor.internal && RESERVED_XML_TAGS.has(extractor.slug)) throw new Error(`Extractor slug "${extractor.slug}" is reserved by Observational Memory.`);
19361
+ const previous = seen.get(extractor.slug);
19362
+ if (previous) throw new Error(`Duplicate extractor slug "${extractor.slug}" from "${previous}" and "${extractor.name}".`);
19363
+ seen.set(extractor.slug, extractor.name);
19364
+ }
19365
+ return [...extractors];
19366
+ }
19367
+ function isJsonLike(value) {
19368
+ return /^(?:[\[{"-]|\d|true\b|false\b|null\b)/.test(value.trim());
19369
+ }
19370
+ function candidateValues(raw) {
19371
+ const trimmed = raw.trim();
19372
+ const candidates = [];
19373
+ const add = (value) => {
19374
+ if (!candidates.some((candidate) => Object.is(candidate, value))) candidates.push(value);
19375
+ };
19376
+ if (isJsonLike(trimmed)) try {
19377
+ add(JSON.parse(trimmed));
19378
+ } catch {}
19379
+ add(trimmed);
19380
+ if (!isJsonLike(trimmed)) try {
19381
+ add(JSON.parse(trimmed));
19382
+ } catch {}
19383
+ return candidates;
19384
+ }
19385
+ function parseExtractorValue(extractor, raw) {
19386
+ const failures = [];
19387
+ for (const candidate of candidateValues(raw)) {
19388
+ const parsed = extractor.schema.safeParse(candidate);
19389
+ if (parsed.success) return parsed.data;
19390
+ failures.push(parsed.error.message);
19391
+ }
19392
+ throw new Error(`Extractor "${extractor.slug}" output did not match its schema: ${failures[0] ?? "invalid value"}`);
19393
+ }
19394
+ function parseExtractedValuesObject(raw) {
19395
+ const trimmed = raw.trim();
19396
+ if (!trimmed || trimmed.startsWith("Write only the extracted values JSON object here.")) return;
19397
+ const parsed = JSON.parse(trimmed);
19398
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(`${EXTRACTED_VALUES_TAG} must contain a JSON object.`);
19399
+ return parsed;
19400
+ }
19401
+ function parseExtractedValues(output, extractors) {
19402
+ const values = {};
19403
+ const failures = [];
19404
+ const inlineExtractors = extractors.filter((extractor) => extractor.mode === "inline");
19405
+ const regex = new RegExp(`<${EXTRACTED_VALUES_TAG}>([\\s\\S]*?)<\\/${EXTRACTED_VALUES_TAG}>`, "gi");
19406
+ const matches = [...output.matchAll(regex)];
19407
+ for (const match of matches) try {
19408
+ const extractedValues = parseExtractedValuesObject(match[1] ?? "");
19409
+ if (!extractedValues) continue;
19410
+ for (const extractor of inlineExtractors) {
19411
+ if (!Object.prototype.hasOwnProperty.call(extractedValues, extractor.slug)) continue;
19412
+ const rawValue = extractedValues[extractor.slug];
19413
+ if (rawValue === void 0 || rawValue === null || rawValue === "") continue;
19414
+ const parsed = extractor.schema.safeParse(rawValue);
19415
+ if (parsed.success) values[extractor.slug] = parsed.data;
19416
+ else failures.push({
19417
+ slug: extractor.slug,
19418
+ error: parsed.error.message
19419
+ });
19420
+ }
19421
+ } catch (error) {
19422
+ failures.push({
19423
+ slug: EXTRACTED_VALUES_TAG,
19424
+ error: error instanceof Error ? error.message : String(error)
19425
+ });
19426
+ }
19427
+ for (const extractor of inlineExtractors) {
19428
+ if (Object.prototype.hasOwnProperty.call(values, extractor.slug)) continue;
19429
+ const tagRegex = new RegExp(`<${extractor.slug}>([\\s\\S]*?)<\\/${extractor.slug}>`, "gi");
19430
+ const rawValue = [...output.matchAll(tagRegex)].at(-1)?.[1]?.trim();
19431
+ if (!rawValue) continue;
19432
+ try {
19433
+ values[extractor.slug] = parseExtractorValue(extractor, rawValue);
19434
+ } catch (error) {
19435
+ failures.push({
19436
+ slug: extractor.slug,
19437
+ error: error instanceof Error ? error.message : String(error)
19438
+ });
19439
+ }
19440
+ }
19441
+ return {
19442
+ values,
19443
+ failures
19444
+ };
19445
+ }
19446
+ function stripExtractorSections(output, extractors) {
19447
+ const inlineExtractors = extractors.filter((extractor) => extractor.mode === "inline");
19448
+ let stripped = output.replace(new RegExp(`[ \\t]*<${EXTRACTED_VALUES_TAG}>[\\s\\S]*?<\\/${EXTRACTED_VALUES_TAG}>\\s*`, "gi"), "");
19449
+ for (const extractor of inlineExtractors) stripped = stripped.replace(new RegExp(`[ \\t]*<${extractor.slug}>[\\s\\S]*?<\\/${extractor.slug}>\\s*`, "gi"), "");
19450
+ return stripped;
19451
+ }
19452
+ function buildExtractorOutputSections(extractors) {
19453
+ const inlineExtractors = extractors.filter((extractor) => extractor.mode === "inline");
19454
+ if (inlineExtractors.length === 0) return "";
19455
+ return `Additional optional XML sections:\nIf the observations include information relevant to any of these tags, output that tag after <observations> and include the relevant information.\n${inlineExtractors.map((extractor) => `<${extractor.slug}>
19456
+ ${extractor.instructions}
19457
+ Include this section when the observations contain relevant information for <${extractor.slug}>. Write only that information inside the tag.
19458
+ </${extractor.slug}>`).join("\n\n")}`;
19459
+ }
19460
+ function renderPriorValue(value) {
19461
+ return typeof value === "string" ? value : JSON.stringify(value);
19462
+ }
19463
+ function buildExtractorPriorLines(extractors, priorExtractedValues) {
19464
+ if (!priorExtractedValues) return [];
19465
+ const lines = [];
19466
+ for (const extractor of extractors) {
19467
+ if (!extractor.includePreviousExtraction) continue;
19468
+ const value = priorExtractedValues[extractor.slug];
19469
+ if (value === void 0 || value === null || value === "") continue;
19470
+ lines.push(`<${extractor.slug}>\n${renderPriorValue(value)}\n</${extractor.slug}>`);
19471
+ }
19472
+ return lines;
19473
+ }
19474
+ const SUBCONSCIOUS_ACTIVITY_STATE_ID = "subconscious-activity";
19475
+ async function getActivityTarget(store, event, scope) {
19476
+ if (event.recordType === "node") {
19477
+ const node = await store.getNode(event.recordId);
19478
+ if (!node || !isKnowledgeScopeVisible(node.scope, scope)) return {
19479
+ id: event.recordId,
19480
+ type: "node"
19481
+ };
19482
+ return {
19483
+ id: node.id,
19484
+ name: node.name,
19485
+ type: "node"
19486
+ };
19487
+ }
19488
+ const record = await store.getKnowledge({
19489
+ id: event.recordId,
19490
+ includeDeleted: true
19491
+ });
19492
+ const node = record ? await store.getNode(record.node) : void 0;
19493
+ if (!node || !isKnowledgeScopeVisible(node.scope, scope)) return {
19494
+ id: event.recordId,
19495
+ type: "node"
19496
+ };
19497
+ return {
19498
+ id: node.id,
19499
+ name: node.name,
19500
+ type: "node"
19501
+ };
19502
+ }
19503
+ async function buildSubconsciousActivitySnapshot(input) {
19504
+ const events = await input.store.listActivity({
19505
+ scope: input.scope,
19506
+ limit: input.recentUpdates
19507
+ });
19508
+ const resolvedUpdates = await Promise.all(events.map(async (event) => {
19509
+ const target = await getActivityTarget(input.store, event, input.scope);
19510
+ return {
19511
+ action: event.action,
19512
+ type: event.recordType,
19513
+ name: target.name,
19514
+ targetId: target.id,
19515
+ targetType: target.type,
19516
+ createdAt: event.createdAt.toISOString()
19517
+ };
19518
+ }));
19519
+ const hotByRecord = /* @__PURE__ */ new Map();
19520
+ for (const update of resolvedUpdates) {
19521
+ if (!update.name) continue;
19522
+ const key = `${update.targetType}:${update.targetId}`;
19523
+ const existing = hotByRecord.get(key);
19524
+ if (existing) existing.updates += 1;
19525
+ else hotByRecord.set(key, {
19526
+ type: update.targetType,
19527
+ name: update.name,
19528
+ updates: 1
19529
+ });
19530
+ }
19531
+ const hot = [...hotByRecord.values()].sort((a, b) => b.updates - a.updates || a.name.localeCompare(b.name)).slice(0, input.recentUpdates);
19532
+ const updates = resolvedUpdates.map((update) => ({
19533
+ action: update.action,
19534
+ type: update.type,
19535
+ ...update.name ? { name: update.name } : {},
19536
+ createdAt: update.createdAt
19537
+ }));
19538
+ const errors = input.errors?.filter(Boolean).slice(0, input.recentUpdates);
19539
+ return {
19540
+ updates,
19541
+ hot,
19542
+ ...errors?.length ? { errors } : {}
19543
+ };
19544
+ }
19545
+ function renderSubconsciousActivity(snapshot) {
19546
+ const lines = snapshot.updates.map((update) => {
19547
+ const target = update.name ? `${update.type} [[${update.name}]]` : update.type;
19548
+ return `- ${update.action}: ${target}`;
19549
+ });
19550
+ const hot = snapshot.hot.map((record) => `[[${record.name}]] (${record.updates})`).join(", ");
19551
+ return [
19552
+ hot ? `Hot: ${hot}` : "Hot: none",
19553
+ "Recent updates:",
19554
+ ...lines.length ? lines : ["- none"],
19555
+ ...snapshot.errors?.length ? ["Errors:", ...snapshot.errors.map((error) => `- ${error}`)] : []
19556
+ ].join("\n");
19557
+ }
19558
+ async function publishSubconsciousError(input) {
19559
+ await input.writer?.custom({
19560
+ type: "data-subconscious-error",
19561
+ data: {
19562
+ error: input.error,
19563
+ agent: input.agent
19564
+ }
19565
+ });
19566
+ if (!input.sendStateSignal) return;
19567
+ const snapshot = {
19568
+ updates: [],
19569
+ hot: [],
19570
+ errors: [input.error]
19571
+ };
19572
+ const contents = renderSubconsciousActivity(snapshot);
19573
+ await input.sendStateSignal({
19574
+ id: SUBCONSCIOUS_ACTIVITY_STATE_ID,
19575
+ mode: "snapshot",
19576
+ cacheKey: createHash("sha256").update(contents).digest("hex"),
19577
+ tagName: "state",
19578
+ attributes: { id: SUBCONSCIOUS_ACTIVITY_STATE_ID },
19579
+ metadata: { origin: "subconscious" },
19580
+ contents,
19581
+ value: snapshot
19582
+ });
19583
+ }
19584
+ async function publishSubconsciousActivity(input) {
19585
+ if (!input.sendStateSignal) return void 0;
19586
+ const snapshot = await buildSubconsciousActivitySnapshot(input);
19587
+ const contents = renderSubconsciousActivity(snapshot);
19588
+ const cacheKey = createHash("sha256").update(contents).digest("hex");
19589
+ await input.sendStateSignal({
19590
+ id: SUBCONSCIOUS_ACTIVITY_STATE_ID,
19591
+ mode: "snapshot",
19592
+ cacheKey,
19593
+ tagName: "state",
19594
+ attributes: { id: SUBCONSCIOUS_ACTIVITY_STATE_ID },
19595
+ metadata: { origin: "subconscious" },
19596
+ contents,
19597
+ value: snapshot
19598
+ });
19599
+ return snapshot;
19600
+ }
19601
+ /** Processor id and state-signal id for the pinned-knowledge lane. */
19602
+ const SUBCONSCIOUS_PINS_STATE_ID = "subconscious-pins";
19603
+ /** Snapshot tag the model sees; the delta tag appends `-update`. */
19604
+ const PINNED_SNAPSHOT_TAG = "pinned-knowledge";
19605
+ const PINNED_DELTA_TAG = "pinned-knowledge-update";
19606
+ /** Reserved node holding the pin set. One record, at one fixed scope level. */
19607
+ const PINNED_NODE_NAME = "pinned";
19608
+ const PINNED_NODE_KIND = "system";
19609
+ const PINNED_NODE_SCOPE_LEVEL = "resource";
19610
+ const DEFAULT_PINNED_MAX_CHARACTERS = 2e3;
19611
+ const MAX_PINNED_MAX_CHARACTERS = 8e3;
19612
+ const PIN_IDENTITY = "subconscious:pin";
19613
+ function pinnedNodeScope(scope, maxScope) {
19614
+ return expandKnowledgeScope(scope, maxScope === "thread" ? "thread" : PINNED_NODE_SCOPE_LEVEL);
19615
+ }
19616
+ async function resolvePinnedNodeId(store, scope) {
19617
+ return (await store.resolveNode({
19618
+ name: PINNED_NODE_NAME,
19619
+ scope
19620
+ }))?.id;
19621
+ }
19622
+ /** Reuse the node wherever it is visible; otherwise create it. `createNode` is an idempotent upsert on (name, scope). */
19623
+ async function ensurePinnedNodeId(store, scope, maxScope) {
19624
+ const existing = await resolvePinnedNodeId(store, scope);
19625
+ if (existing) return existing;
19626
+ return (await store.createNode({
19627
+ name: PINNED_NODE_NAME,
19628
+ kind: PINNED_NODE_KIND,
19629
+ scope: pinnedNodeScope(scope, maxScope)
19630
+ })).id;
19631
+ }
19632
+ /**
19633
+ * Assembles the current pin set.
19634
+ *
19635
+ * Reads use the FULL visible scope context, never a level-narrowed write scope: visibility is
19636
+ * subset containment, so querying at the node's level would drop pins written at narrower
19637
+ * levels. Deleted records are excluded explicitly.
19638
+ */
19639
+ async function listPinnedKnowledge(input) {
19640
+ const nodeId = await resolvePinnedNodeId(input.store, input.scope);
19641
+ if (!nodeId) return { pins: [] };
19642
+ const pins = [];
19643
+ let after;
19644
+ do {
19645
+ const page = await input.store.listKnowledgeAbout({
19646
+ node: nodeId,
19647
+ scope: input.scope,
19648
+ after,
19649
+ includeDeleted: false
19650
+ });
19651
+ pins.push(...page.records);
19652
+ after = page.nextCursor;
19653
+ } while (after);
19654
+ return {
19655
+ nodeId,
19656
+ pins
19657
+ };
19658
+ }
19659
+ function totalCharacters(pins) {
19660
+ return pins.reduce((sum, pin) => sum + pin.text.length, 0);
19661
+ }
19662
+ function assertBudget(options, pins, incomingText, replacing) {
19663
+ const kept = replacing ? pins.filter((pin) => pin.id !== replacing.id) : pins;
19664
+ if (!replacing && kept.length >= options.maxPins) throw new Error(`Pin limit reached: the set holds at most ${options.maxPins}. Unpin something first.`);
19665
+ if (totalCharacters(kept) + incomingText.length > options.maxCharacters) throw new Error(`Pin budget exceeded: the pin set is limited to ${options.maxCharacters} characters in total.`);
19666
+ }
19667
+ function clampPinLevel(level) {
19668
+ return level === "org" ? "resource" : level;
19669
+ }
19670
+ function resolveWriteScope$1(options, level) {
19671
+ let effective = clampPinLevel(level ?? options.defaultScope);
19672
+ if (!level && options.maxScope === "thread") effective = "thread";
19673
+ const scope = expandKnowledgeScope(options.scope, effective);
19674
+ assertKnowledgeScopeWithinCeiling(scope, options.maxScope);
19675
+ return scope;
19676
+ }
19677
+ const scopeLevelSchema$1 = {
19678
+ type: "string",
19679
+ enum: ["resource", "thread"]
19680
+ };
19681
+ /** Shared pin write path used by the tool and capture-time pinning. */
19682
+ async function writePinnedKnowledge(store, options, text, level, metadata) {
19683
+ const { pins } = await listPinnedKnowledge({
19684
+ store,
19685
+ scope: options.scope
19686
+ });
19687
+ assertBudget(options, pins, text);
19688
+ const nodeId = await ensurePinnedNodeId(store, options.scope, options.maxScope);
19689
+ return store.appendKnowledge({
19690
+ node: nodeId,
19691
+ text,
19692
+ scope: resolveWriteScope$1(options, level),
19693
+ sourceThreadId: options.sourceThreadId,
19694
+ maxScope: options.maxScope,
19695
+ metadata,
19696
+ resolutionScope: options.scope,
19697
+ defaultScope: expandKnowledgeScope(options.scope, options.defaultScope)
19698
+ });
19699
+ }
19700
+ async function getStore$1(memory) {
19701
+ const store = await memory.storage.getStore("knowledge");
19702
+ if (!store) throw new Error("Pinned knowledge requires a configured knowledge storage domain.");
19703
+ return store;
19704
+ }
19705
+ async function requirePin(store, recordId, options) {
19706
+ const record = await store.getKnowledge({
19707
+ id: recordId,
19708
+ includeDeleted: false
19709
+ });
19710
+ if (!record) throw new Error(`Pin not found: ${recordId}`);
19711
+ const nodeId = await resolvePinnedNodeId(store, options.scope);
19712
+ if (!nodeId || record.node !== nodeId) throw new Error(`Record is not a pin: ${recordId}`);
19713
+ if (!isKnowledgeScopeVisible(record.scope, options.scope)) throw new Error("Pin is outside the visible scope.");
19714
+ return record;
19715
+ }
19716
+ /**
19717
+ * Pin lifecycle tools. Pin appends a record on the reserved node; unpin soft-deletes it
19718
+ * (auditable, restorable); edit is remove plus append because knowledge records are immutable,
19719
+ * so an edited pin carries a new record id.
19720
+ */
19721
+ function createPinnedTools(memory, options) {
19722
+ return {
19723
+ knowledge_pin: createTool({
19724
+ id: "knowledge_pin",
19725
+ description: "Pin knowledge that must stay in context every turn without being asked for. Pins cost context permanently; pin only what is unconditionally relevant.",
19726
+ inputSchema: {
19727
+ type: "object",
19728
+ properties: {
19729
+ text: {
19730
+ type: "string",
19731
+ minLength: 1
19732
+ },
19733
+ scope: scopeLevelSchema$1,
19734
+ reason: {
19735
+ type: "string",
19736
+ minLength: 1,
19737
+ description: "One short sentence: why this must stay in context permanently."
19738
+ }
19739
+ },
19740
+ required: ["text"],
19741
+ additionalProperties: false
19742
+ },
19743
+ execute: async (input) => {
19744
+ const value = input;
19745
+ return writePinnedKnowledge(await getStore$1(memory), options, value.text, value.scope, value.reason ? { reason: value.reason } : void 0);
19746
+ }
19747
+ }),
19748
+ knowledge_unpin: createTool({
19749
+ id: "knowledge_unpin",
19750
+ description: "Remove a pin. The underlying knowledge record is soft-deleted and drops out of the pinned context.",
19751
+ inputSchema: {
19752
+ type: "object",
19753
+ properties: { recordId: {
19754
+ type: "string",
19755
+ minLength: 1
19756
+ } },
19757
+ required: ["recordId"],
19758
+ additionalProperties: false
19759
+ },
19760
+ execute: async (input) => {
19761
+ const store = await getStore$1(memory);
19762
+ const record = await requirePin(store, input.recordId, options);
19763
+ return store.removeKnowledge({
19764
+ id: record.id,
19765
+ deletedBy: PIN_IDENTITY
19766
+ });
19767
+ }
19768
+ }),
19769
+ knowledge_edit_pin: createTool({
19770
+ id: "knowledge_edit_pin",
19771
+ description: "Replace the text of an existing pin. The replacement carries a new knowledge record id.",
19772
+ inputSchema: {
19773
+ type: "object",
19774
+ properties: {
19775
+ recordId: {
19776
+ type: "string",
19777
+ minLength: 1
19778
+ },
19779
+ text: {
19780
+ type: "string",
19781
+ minLength: 1
19782
+ },
19783
+ reason: {
19784
+ type: "string",
19785
+ minLength: 1,
19786
+ description: "One short sentence: why this must stay in context permanently."
19787
+ }
19788
+ },
19789
+ required: ["recordId", "text"],
19790
+ additionalProperties: false
19791
+ },
19792
+ execute: async (input) => {
19793
+ const value = input;
19794
+ const store = await getStore$1(memory);
19795
+ const record = await requirePin(store, value.recordId, options);
19796
+ const { pins } = await listPinnedKnowledge({
19797
+ store,
19798
+ scope: options.scope
19799
+ });
19800
+ assertBudget(options, pins, value.text, record);
19801
+ await store.removeKnowledge({
19802
+ id: record.id,
19803
+ deletedBy: PIN_IDENTITY
19804
+ });
19805
+ return store.appendKnowledge({
19806
+ node: record.node,
19807
+ text: value.text,
19808
+ scope: record.scope,
19809
+ sourceThreadId: options.sourceThreadId,
19810
+ maxScope: record.maxScope,
19811
+ metadata: value.reason ? {
19812
+ ...record.metadata,
19813
+ reason: value.reason
19814
+ } : record.metadata,
19815
+ resolutionScope: options.scope,
19816
+ defaultScope: expandKnowledgeScope(options.scope, options.defaultScope)
19817
+ });
19818
+ }
19819
+ })
19820
+ };
19821
+ }
19822
+ /**
19823
+ * Resolves the resource rung of a subconscious knowledge scope.
19824
+ *
19825
+ * When the request context carries a `knowledgeResourceId` override, every
19826
+ * scope resolver anchors the resource rung on it instead of the run's
19827
+ * resourceId. This lets a host (for example, the factory) share one knowledge
19828
+ * graph across many runs of the same project while leaving thread identity and
19829
+ * observational memory untouched. Without the override, behavior is unchanged:
19830
+ * the fallback (the run's resourceId) is used as-is.
19831
+ */
19832
+ function resolveKnowledgeResourceId(requestContext, fallback) {
19833
+ const override = requestContext?.get?.("knowledgeResourceId");
19834
+ if (typeof override === "string" && override.trim()) return override;
19835
+ return fallback;
19836
+ }
19837
+ const CAPTURE_GUIDANCE_PAGE = "capture-guidance";
19838
+ const MAX_CAPTURE_GUIDANCE_LENGTH = 4e3;
19839
+ const SCOPE_ORDER = {
19840
+ org: 0,
19841
+ resource: 1,
19842
+ thread: 2
19843
+ };
19844
+ const subconsciousCaptureSchema = z$2.object({ nodes: z$2.array(z$2.object({
19845
+ name: z$2.string().trim().min(1),
19846
+ kind: z$2.string().trim().min(1),
19847
+ scope: z$2.enum([
19848
+ "org",
19849
+ "resource",
19850
+ "thread"
19851
+ ]).optional(),
19852
+ records: z$2.array(z$2.object({
19853
+ text: z$2.string().trim().min(1),
19854
+ scope: z$2.enum([
19855
+ "org",
19856
+ "resource",
19857
+ "thread"
19858
+ ]).optional(),
19859
+ when: z$2.string().trim().min(1).optional(),
19860
+ reason: z$2.string().trim().min(1)
19861
+ }))
19862
+ })) });
19863
+ const subconsciousCapturePinningSchema = z$2.object({ nodes: z$2.array(z$2.object({
19864
+ name: z$2.string().trim().min(1),
19865
+ kind: z$2.string().trim().min(1),
19866
+ scope: z$2.enum([
19867
+ "org",
19868
+ "resource",
19869
+ "thread"
19870
+ ]).optional(),
19871
+ records: z$2.array(z$2.object({
19872
+ text: z$2.string().trim().min(1),
19873
+ scope: z$2.enum([
19874
+ "org",
19875
+ "resource",
19876
+ "thread"
19877
+ ]).optional(),
19878
+ when: z$2.string().trim().min(1).optional(),
19879
+ reason: z$2.string().trim().min(1),
19880
+ pin: z$2.boolean().optional()
19881
+ }))
19882
+ })) });
19883
+ const CAPTURE_PINNING_INSTRUCTIONS = `Mark pin: true only for durable user preferences or hard constraints that should apply in every future session without being asked for.`;
19884
+ const CAPTURE_INSTRUCTIONS = `Extract durable, explicitly stated knowledge from the observations.
19885
+ Return nodes with short stable names, a freeform kind, and knowledge records nested under the node each record is about.
19886
+ Use common kinds such as person, task, event, project, organization, or document when they fit.
19887
+ Set node scope to the narrowest level where that identity and content should be shared. Omit it to use the configured default scope.
19888
+ Knowledge records must be grounded in the conversation, concise, and written as prose. Do not infer unstated information.
19889
+ Wrap every named node mentioned in record text in [[wikilinks]].
19890
+ Set a record scope only when the conversation establishes where it applies. Use org for organization-wide records, resource for records shared across this resource's conversations, and thread for conversation-private records.
19891
+ Omit scope when uncertain; omitted record scopes stay private to the current thread.
19892
+ Emit when only when the conversation anchors the referred time. Resolve relative dates against the current date and use ISO 8601.
19893
+ Capture what was learned through the work, not what the session was told: skip records that merely restate standing instructions, configured rules, or the text of the task or issue the session was handed. The exception is an explicit request from the user to remember something, which is always captured even when it duplicates an existing instruction.`;
19894
+ const CAPTURE_REASON_INSTRUCTIONS = `Every record requires a reason: the concrete why behind capturing it, in one short sentence - what it cost to learn or when it will matter again (and for pinned records, why it must stay in context). Never write generic filler such as "seemed relevant" or "useful context".`;
19895
+ function clampScope(level, ceiling) {
19896
+ return ceiling && SCOPE_ORDER[level] < SCOPE_ORDER[ceiling] ? ceiling : level;
19897
+ }
19898
+ function requireScopeContext(context) {
19899
+ const organizationId = context.requestContext?.get("organizationId");
19900
+ if (typeof organizationId !== "string" || !organizationId.trim()) throw new Error("Subconscious requires requestContext.organizationId to derive scoped knowledge. Set organizationId on the request context for this conversation.");
19901
+ const resourceId = resolveKnowledgeResourceId(context.requestContext, context.resourceId);
19902
+ if (!resourceId) throw new Error("Subconscious requires resourceId to derive scoped knowledge.");
19903
+ if (!context.threadId) throw new Error("Subconscious requires threadId to derive scoped knowledge.");
19904
+ return [
19905
+ `org:${organizationId}`,
19906
+ `resource:${resourceId}`,
19907
+ `thread:${context.threadId}`
19908
+ ];
19909
+ }
19910
+ async function getKnowledgeStore$1(context) {
19911
+ if (!context.memory) throw new Error("Subconscious capture requires an active Memory instance.");
19912
+ const store = await context.memory.storage.getStore("knowledge");
19913
+ if (!store) throw new Error("Subconscious requires a knowledge storage domain. Configure a storage adapter that provides stores.knowledge.");
19914
+ return store;
19915
+ }
19916
+ function parseWhen(value) {
19917
+ if (!value) return void 0;
19918
+ const when = new Date(value);
19919
+ if (Number.isNaN(when.getTime())) throw new Error(`Invalid Subconscious record time: ${value}`);
19920
+ return when;
19921
+ }
19922
+ var SubconsciousCaptureExtractor = class extends Extractor {
19923
+ constructor(options) {
19924
+ const capturePinning = options.pins !== false && options.pins !== void 0 && options.pins.capturePinning;
19925
+ const pinNotes = /* @__PURE__ */ new WeakMap();
19926
+ const defaultImplementation = async (context) => {
19927
+ const scopeContext = requireScopeContext(context);
19928
+ const store = await getKnowledgeStore$1(context);
19929
+ const droppedPins = [];
19930
+ for (const extractedNode of context.current.nodes) {
19931
+ const nodeScope = expandKnowledgeScope(scopeContext, clampScope(extractedNode.scope ?? options.defaultScope, options.maxScope));
19932
+ const node = await store.createNode({
19933
+ name: extractedNode.name,
19934
+ kind: extractedNode.kind,
19935
+ scope: nodeScope
19936
+ });
19937
+ for (const extractedKnowledge of extractedNode.records) {
19938
+ if (capturePinning && extractedKnowledge.pin === true && options.pins) {
19939
+ try {
19940
+ await writePinnedKnowledge(store, {
19941
+ scope: scopeContext,
19942
+ sourceThreadId: context.threadId,
19943
+ defaultScope: options.defaultScope,
19944
+ maxScope: options.maxScope,
19945
+ maxPins: options.pins.maxPins,
19946
+ maxCharacters: options.pins.maxCharacters
19947
+ }, extractedKnowledge.text, extractedKnowledge.scope, extractedKnowledge.reason ? { reason: extractedKnowledge.reason } : void 0);
19948
+ } catch (error) {
19949
+ droppedPins.push(`Capture-time pin dropped: ${error instanceof Error ? error.message : String(error)}`);
19950
+ }
19951
+ continue;
19952
+ }
19953
+ const knowledgeLevel = clampScope(extractedKnowledge.scope ?? "thread", options.maxScope);
19954
+ await store.appendKnowledge({
19955
+ node,
19956
+ text: extractedKnowledge.text,
19957
+ scope: expandKnowledgeScope(scopeContext, knowledgeLevel),
19958
+ sourceThreadId: context.threadId,
19959
+ when: parseWhen(extractedKnowledge.when),
19960
+ maxScope: options.maxScope,
19961
+ metadata: extractedKnowledge.reason ? { reason: extractedKnowledge.reason } : void 0,
19962
+ resolutionScope: scopeContext,
19963
+ defaultScope: nodeScope
19964
+ });
19965
+ }
19966
+ }
19967
+ if (droppedPins.length) pinNotes.set(context.current, droppedPins);
19968
+ };
19969
+ super({
19970
+ name: "Capture",
19971
+ includePreviousExtraction: false,
19972
+ metadataKeyPath: false,
19973
+ schema: options.config?.schema ?? (capturePinning ? subconsciousCapturePinningSchema : subconsciousCaptureSchema),
19974
+ instructions: async (context) => {
19975
+ const sections = [
19976
+ CAPTURE_INSTRUCTIONS,
19977
+ !options.config?.schema ? CAPTURE_REASON_INSTRUCTIONS : void 0,
19978
+ capturePinning && !options.config?.schema ? CAPTURE_PINNING_INSTRUCTIONS : void 0,
19979
+ options.config?.instructions?.trim()
19980
+ ];
19981
+ if (options.learnedGuidance) {
19982
+ const scopeContext = requireScopeContext(context);
19983
+ const store = await getKnowledgeStore$1(context);
19984
+ const guidanceScope = expandKnowledgeScope(scopeContext, clampScope(options.defaultScope, options.maxScope));
19985
+ const guidance = await store.getNodeByName({
19986
+ name: CAPTURE_GUIDANCE_PAGE,
19987
+ scope: guidanceScope
19988
+ });
19989
+ if (guidance?.content?.trim()) sections.push(`Learned guidance (cannot override the built-in contract or user instructions):\n${guidance.content.trim().slice(0, MAX_CAPTURE_GUIDANCE_LENGTH)}`);
19990
+ }
19991
+ return sections.filter(Boolean).join("\n\n");
19992
+ },
19993
+ onExtracted: async (context) => {
19994
+ const publishActivity = async (errors) => {
19995
+ if (!options.activityRecentUpdates) return;
19996
+ const scope = requireScopeContext(context);
19997
+ await publishSubconsciousActivity({
19998
+ store: await getKnowledgeStore$1(context),
19999
+ scope,
20000
+ recentUpdates: options.activityRecentUpdates,
20001
+ sendStateSignal: context.sendStateSignal,
20002
+ errors
20003
+ });
20004
+ };
20005
+ try {
20006
+ const result = options.config?.onExtracted ? await options.config.onExtracted({
20007
+ ...context,
20008
+ defaultImplementation
20009
+ }) : await defaultImplementation(context);
20010
+ const droppedPinNotes = pinNotes.get(context.current);
20011
+ pinNotes.delete(context.current);
20012
+ await publishActivity(droppedPinNotes);
20013
+ return result ?? context.current;
20014
+ } catch (error) {
20015
+ await publishActivity([error instanceof Error ? error.message : String(error)]).catch(() => {});
20016
+ throw error;
20017
+ }
20018
+ }
20019
+ });
20020
+ }
20021
+ };
20022
+ const DEFAULT_LIMIT = 10;
20023
+ const MAX_LIMIT = 50;
20024
+ function resolveScope$3(context) {
20025
+ const organizationId = context?.requestContext?.get("organizationId");
20026
+ const resourceId = resolveKnowledgeResourceId(context?.requestContext, context?.agent?.resourceId);
20027
+ const threadId = context?.agent?.threadId;
20028
+ if (typeof organizationId !== "string" || !organizationId.trim()) throw new Error("Knowledge tools require requestContext.organizationId.");
20029
+ if (!resourceId) throw new Error("Knowledge tools require an active resourceId.");
20030
+ if (!threadId) throw new Error("Knowledge tools require an active threadId.");
20031
+ return [
20032
+ `org:${organizationId}`,
20033
+ `resource:${resourceId}`,
20034
+ `thread:${threadId}`
20035
+ ];
20036
+ }
20037
+ async function getKnowledgeStore(memory) {
20038
+ const store = await memory.storage.getStore("knowledge");
20039
+ if (!store) throw new Error("Knowledge tools require a configured knowledge storage domain.");
20040
+ return store;
20041
+ }
20042
+ function normalizeLimit(limit) {
20043
+ return Math.min(Math.max(limit ?? DEFAULT_LIMIT, 1), MAX_LIMIT);
20044
+ }
20045
+ function serializeRecord(record) {
20046
+ return {
20047
+ id: record.id,
20048
+ text: record.text,
20049
+ scope: record.scope,
20050
+ sourceThreadId: record.sourceThreadId,
20051
+ capturedAt: record.capturedAt.toISOString(),
20052
+ when: record.when?.toISOString()
20053
+ };
20054
+ }
20055
+ function serializeNode(node) {
20056
+ return {
20057
+ id: node.id,
20058
+ type: node.type,
20059
+ name: node.name,
20060
+ kind: node.kind,
20061
+ content: node.content,
20062
+ scope: node.scope,
20063
+ version: node.version,
20064
+ updatedAt: node.updatedAt.toISOString()
20065
+ };
20066
+ }
20067
+ async function loadSemanticResult(store, scope, candidate) {
20068
+ const type = candidate.metadata?.document_type;
20069
+ if (type === "node") {
20070
+ const node = await store.getNode(candidate.id.slice(15));
20071
+ if (!node || node.mergedInto || !isKnowledgeScopeVisible(node.scope, scope)) return null;
20072
+ return {
20073
+ type: "node",
20074
+ id: node.id,
20075
+ recordId: node.id,
20076
+ name: node.name,
20077
+ text: `${node.name}\n${node.content ?? ""}`,
20078
+ scope: node.scope,
20079
+ semanticScore: candidate.score
20080
+ };
20081
+ }
20082
+ if (type === "record") {
20083
+ const record = await store.getKnowledge({ id: candidate.id.slice(17) });
20084
+ if (!record || !isKnowledgeScopeVisible(record.scope, scope)) return null;
20085
+ const node = await store.getNode(record.node);
20086
+ const parentVisible = Boolean(node && !node.mergedInto && isKnowledgeScopeVisible(node.scope, scope));
20087
+ return {
20088
+ type: "record",
20089
+ id: record.id,
20090
+ recordId: parentVisible ? node.id : record.id,
20091
+ name: parentVisible ? node.name : "(private node)",
20092
+ text: record.text,
20093
+ scope: record.scope,
20094
+ semanticScore: candidate.score
20095
+ };
20096
+ }
20097
+ return null;
20098
+ }
20099
+ function mergeHybridResults(lexical, semantic, limit) {
20100
+ const ranked = /* @__PURE__ */ new Map();
20101
+ lexical.forEach((result, index) => {
20102
+ ranked.set(`${result.type}:${result.id}`, {
20103
+ ...result,
20104
+ score: 1 / (60 + index + 1),
20105
+ sources: ["lexical"]
20106
+ });
20107
+ });
20108
+ semantic.forEach((result, index) => {
20109
+ const key = `${result.type}:${result.id}`;
20110
+ const existing = ranked.get(key);
20111
+ const reciprocalRank = 1 / (60 + index + 1);
20112
+ ranked.set(key, {
20113
+ ...result,
20114
+ score: (existing?.score ?? 0) + reciprocalRank,
20115
+ sources: existing ? ["lexical", "semantic"] : ["semantic"],
20116
+ semanticScore: result.semanticScore
20117
+ });
20118
+ });
20119
+ return [...ranked.values()].sort((left, right) => right.score - left.score || left.id.localeCompare(right.id)).slice(0, limit);
20120
+ }
20121
+ function createKnowledgeTools(memory, fixedScope) {
20122
+ return {
20123
+ knowledge_search: createTool({
20124
+ id: "knowledge_search",
20125
+ description: "Search durable scoped knowledge across nodes and knowledge records using lexical and semantic retrieval.",
20126
+ inputSchema: {
20127
+ type: "object",
20128
+ properties: {
20129
+ query: {
20130
+ type: "string",
20131
+ minLength: 1,
20132
+ description: "The knowledge to search for."
20133
+ },
20134
+ limit: {
20135
+ type: "integer",
20136
+ minimum: 1,
20137
+ maximum: MAX_LIMIT,
20138
+ description: "Maximum results. Defaults to 10."
20139
+ }
20140
+ },
20141
+ required: ["query"],
20142
+ additionalProperties: false
20143
+ },
20144
+ execute: async (input, context) => {
20145
+ const { query, limit: requestedLimit } = input;
20146
+ const scope = fixedScope ?? resolveScope$3(context);
20147
+ const limit = normalizeLimit(requestedLimit);
20148
+ const store = await getKnowledgeStore(memory);
20149
+ const semanticCandidates = await memory.getKnowledgeSemanticIndex().then((index) => index.search(query, scope, limit * 2));
20150
+ return {
20151
+ query,
20152
+ results: mergeHybridResults(await store.search({
20153
+ query,
20154
+ scope,
20155
+ limit: limit * 2
20156
+ }), (await Promise.all(semanticCandidates.map((candidate) => loadSemanticResult(store, scope, candidate)))).filter((result) => Boolean(result)), limit)
20157
+ };
20158
+ }
20159
+ }),
20160
+ knowledge_read: createTool({
20161
+ id: "knowledge_read",
20162
+ description: "Read a knowledge node, its content, and knowledge records about or linked to it by name or ID.",
20163
+ inputSchema: {
20164
+ type: "object",
20165
+ properties: {
20166
+ id: {
20167
+ type: "string",
20168
+ minLength: 1
20169
+ },
20170
+ name: {
20171
+ type: "string",
20172
+ minLength: 1
20173
+ },
20174
+ relationship: {
20175
+ type: "string",
20176
+ enum: [
20177
+ "about",
20178
+ "mentioning",
20179
+ "related"
20180
+ ],
20181
+ description: "Knowledge relationship to query. Defaults to about."
20182
+ },
20183
+ cursor: {
20184
+ type: "string",
20185
+ minLength: 1,
20186
+ description: "Return knowledge records after this record ULID."
20187
+ },
20188
+ limit: {
20189
+ type: "integer",
20190
+ minimum: 1,
20191
+ maximum: MAX_LIMIT
20192
+ }
20193
+ },
20194
+ additionalProperties: false
20195
+ },
20196
+ execute: async (input, context) => {
20197
+ const { id, name, relationship = "about", cursor, limit: requestedLimit } = input;
20198
+ if (!id && !name) throw new Error("knowledge_read requires id or name.");
20199
+ const scope = fixedScope ?? resolveScope$3(context);
20200
+ const store = await getKnowledgeStore(memory);
20201
+ const node = id ? await store.getNode(id) : await store.resolveNode({
20202
+ name,
20203
+ scope
20204
+ });
20205
+ if (!node || node.mergedInto || !isKnowledgeScopeVisible(node.scope, scope)) return { found: false };
20206
+ const result = await (relationship === "related" ? store.listKnowledgeRelatedTo : relationship === "mentioning" ? store.listKnowledgeMentioning : store.listKnowledgeAbout).call(store, {
20207
+ node,
20208
+ scope,
20209
+ after: cursor,
20210
+ limit: normalizeLimit(requestedLimit)
20211
+ });
20212
+ return {
20213
+ found: true,
20214
+ node: serializeNode(node),
20215
+ records: result.records.map(serializeRecord),
20216
+ nextCursor: result.nextCursor
20217
+ };
20218
+ }
20219
+ }),
20220
+ knowledge_browse: createTool({
20221
+ id: "knowledge_browse",
20222
+ description: "Browse visible knowledge nodes by scope and name prefix, or follow a node’s mentions and backlinks.",
20223
+ inputSchema: {
20224
+ type: "object",
20225
+ properties: {
20226
+ namePrefix: { type: "string" },
20227
+ kind: {
20228
+ type: "string",
20229
+ description: "Optional node kind filter."
20230
+ },
20231
+ hasContent: {
20232
+ type: "boolean",
20233
+ description: "Filter nodes by whether they have long-form content."
20234
+ },
20235
+ node: {
20236
+ type: "string",
20237
+ minLength: 1,
20238
+ description: "When set, return knowledge related to this node."
20239
+ },
20240
+ cursor: {
20241
+ type: "string",
20242
+ minLength: 1
20243
+ },
20244
+ limit: {
20245
+ type: "integer",
20246
+ minimum: 1,
20247
+ maximum: MAX_LIMIT
20248
+ }
20249
+ },
20250
+ additionalProperties: false
20251
+ },
20252
+ execute: async (input, context) => {
20253
+ const { namePrefix, kind, hasContent, node: nodeReference, cursor, limit: requestedLimit } = input;
20254
+ const scope = fixedScope ?? resolveScope$3(context);
20255
+ const limit = normalizeLimit(requestedLimit);
20256
+ const store = await getKnowledgeStore(memory);
20257
+ if (nodeReference) {
20258
+ const node = await store.getNode(nodeReference);
20259
+ if (!node || node.mergedInto || !isKnowledgeScopeVisible(node.scope, scope)) return { found: false };
20260
+ const result = await store.listKnowledgeRelatedTo({
20261
+ node,
20262
+ scope,
20263
+ after: cursor,
20264
+ limit
20265
+ });
20266
+ return {
20267
+ found: true,
20268
+ node: serializeNode(node),
20269
+ records: result.records.map(serializeRecord),
20270
+ nextCursor: result.nextCursor
20271
+ };
20272
+ }
20273
+ const nodes = await store.listNodes({
20274
+ scope,
20275
+ namePrefix,
20276
+ kind,
20277
+ hasContent,
20278
+ cursor,
20279
+ limit: limit + 1
20280
+ });
20281
+ const hasMore = nodes.length > limit;
20282
+ const visibleNodes = nodes.slice(0, limit);
20283
+ return {
20284
+ nodes: visibleNodes.map(serializeNode),
20285
+ nextCursor: hasMore ? createKnowledgeNodeCursor(visibleNodes.at(-1), {
20286
+ namePrefix,
20287
+ kind,
20288
+ hasContent
20289
+ }) : void 0
20290
+ };
20291
+ }
20292
+ })
20293
+ };
20294
+ }
20295
+ function isTieredModelTarget(model) {
20296
+ if (typeof model === "string") return true;
20297
+ if (!model || typeof model !== "object") return false;
20298
+ return "modelId" in model || "id" in model || "providerId" in model || "provider" in model || "doGenerate" in model && "doStream" in model;
20299
+ }
20300
+ function normalizeThresholds(config) {
20301
+ const entries = Object.entries(config.upTo);
20302
+ if (entries.length === 0) throw new Error("ModelByInputTokens requires at least one threshold in \"upTo\"");
20303
+ for (const [limitStr, model] of entries) {
20304
+ const limit = Number(limitStr);
20305
+ if (!Number.isFinite(limit) || limit <= 0) throw new Error(`ModelByInputTokens threshold keys must be positive numbers. Got: ${limitStr}`);
20306
+ if (!isTieredModelTarget(model)) throw new Error(`ModelByInputTokens requires a valid model target for threshold ${limitStr}`);
20307
+ }
20308
+ return entries.map(([limitStr, model]) => ({
20309
+ limit: Number(limitStr),
20310
+ model
20311
+ })).sort((a, b) => a.limit - b.limit);
20312
+ }
20313
+ var ModelByInputTokens = class {
20314
+ thresholds;
20315
+ constructor(config) {
20316
+ this.thresholds = normalizeThresholds(config);
20317
+ }
20318
+ resolve(inputTokens) {
20319
+ for (const { limit, model } of this.thresholds) if (inputTokens <= limit) return model;
20320
+ const maxLimit = this.thresholds[this.thresholds.length - 1].limit;
20321
+ throw new Error(`ModelByInputTokens: input token count (${inputTokens}) exceeds the largest configured threshold (${maxLimit}). Please configure a higher threshold or use a larger model.`);
20322
+ }
20323
+ getThresholds() {
20324
+ return this.thresholds.map((t) => t.limit);
20325
+ }
20326
+ };
20327
+ /**
20328
+ * Normalize an observational memory model config into something an Agent can consume directly.
20329
+ * Returns undefined when the OM model cannot stand alone: the 'default' sentinel and
20330
+ * token-routed models (ModelByInputTokens) both require engine context to resolve.
20331
+ */
20332
+ function usableObservationalMemoryModel(model) {
20333
+ if (!model || model === "default") return void 0;
20334
+ if (model instanceof ModelByInputTokens) return void 0;
20335
+ if (Array.isArray(model)) return model[0]?.model;
20336
+ if (typeof model === "function") return (async (ctx) => {
20337
+ const result = await model(ctx);
20338
+ return Array.isArray(result) ? result[0]?.model ?? result : result;
20339
+ });
20340
+ return model;
20341
+ }
20342
+ /**
20343
+ * Resolve the model a subconscious agent runs on. Precedence: the per-agent config model,
20344
+ * then the observational memory model, then the main agent's model. Returns undefined when
20345
+ * no source is available so callers keep their existing throw/silent-return behavior.
20346
+ */
20347
+ async function resolveSubconsciousAgentModel(options) {
20348
+ const { config, omModel, mainAgent, requestContext } = options;
20349
+ if (config.model) {
20350
+ if (mainAgent) return await mainAgent.getModel({
20351
+ requestContext,
20352
+ modelConfig: config.model
20353
+ });
20354
+ return config.model;
20355
+ }
20356
+ const fromOm = usableObservationalMemoryModel(omModel);
20357
+ if (fromOm) return fromOm;
20358
+ if (mainAgent) return await mainAgent.getModel({ requestContext });
20359
+ }
20360
+ const DEFAULT_INSTRUCTIONS$2 = `Review the current observations and use the knowledge tools to find prior knowledge that is directly relevant now.
20361
+
20362
+ Be selective. Treat future-dated records as relevant when their time is imminent or useful to the current task. When the observations show whether an earlier reminder was used, tune your selectivity accordingly without storing hit/miss counters.
20363
+ Never remind about knowledge that is already visible in the current observations or recent messages — a reminder is only valuable for knowledge the agent can no longer see. Echoing back what was just said or just captured is noise.
20364
+ If nothing is relevant, respond with exactly <no-reminder /> and nothing else.
20365
+ If knowledge is relevant, return one concise reminder that explains why it matters and includes source node or record IDs. Do not invent knowledge and do not expose knowledge outside the tools' scoped results.`;
20366
+ /** Own-thread records younger than this are treated as still-in-context and excluded from reminder candidates. */
20367
+ const FRESH_OWN_RECORD_WINDOW_MS = 1800 * 1e3;
20368
+ function resolveScope$2(context) {
20369
+ const organizationId = context.requestContext?.get("organizationId");
20370
+ if (typeof organizationId !== "string" || !organizationId.trim()) throw new Error("Subconscious remind requires organizationId in the request context.");
20371
+ const resourceId = resolveKnowledgeResourceId(context.requestContext, context.resourceId);
20372
+ if (!resourceId) throw new Error("Subconscious remind requires a resourceId.");
20373
+ return canonicalizeKnowledgeScope([
20374
+ `org:${organizationId}`,
20375
+ `resource:${resourceId}`,
20376
+ `thread:${context.threadId}`
20377
+ ]);
20378
+ }
20379
+ const REMINDER_QUERY_STOP_WORDS = /* @__PURE__ */ new Set([
20380
+ "about",
20381
+ "after",
20382
+ "before",
20383
+ "current",
20384
+ "from",
20385
+ "have",
20386
+ "observations",
20387
+ "that",
20388
+ "their",
20389
+ "there",
20390
+ "they",
20391
+ "this",
20392
+ "user",
20393
+ "what",
20394
+ "when",
20395
+ "where",
20396
+ "which",
20397
+ "with"
20398
+ ]);
20399
+ async function findReminderSources(store, scope, observations) {
20400
+ const terms = [...new Set(observations.match(/[A-Za-z0-9][A-Za-z0-9_-]{3,}/g)?.map((term) => term.toLowerCase()).filter((term) => !REMINDER_QUERY_STOP_WORDS.has(term)) ?? [])].slice(0, 12);
20401
+ const results = (await Promise.all(terms.map((query) => store.search({
20402
+ query,
20403
+ scope,
20404
+ limit: 5
20405
+ })))).flat();
20406
+ return [...new Map(results.map((result) => [`${result.type}:${result.id}`, result])).values()].slice(0, 10);
20407
+ }
20408
+ /**
20409
+ * Drop the current thread's own freshly captured KnowledgeRecords from the candidate list. They match the
20410
+ * current observations almost perfectly (they were just distilled from them), so without this
20411
+ * guard the reminder agent mostly echoes the session's own words back at it.
20412
+ */
20413
+ async function dropFreshOwnRecords(store, sources, threadId) {
20414
+ const checks = await Promise.all(sources.map(async (source) => {
20415
+ if (source.type !== "record") return true;
20416
+ const record = await store.getKnowledge({ id: source.id }).catch(() => null);
20417
+ if (!record) return true;
20418
+ const isOwnThread = record.sourceThreadId === threadId || record.sourceThreadId.startsWith(`subconscious:${threadId}:`);
20419
+ const isFresh = Date.now() - new Date(record.capturedAt).getTime() < FRESH_OWN_RECORD_WINDOW_MS;
20420
+ return !(isOwnThread && isFresh);
20421
+ }));
20422
+ return sources.filter((_, index) => checks[index]);
20423
+ }
20424
+ var SubconsciousRemindExtractor = class extends Extractor {
20425
+ constructor(config, omModel) {
20426
+ super({
20427
+ name: "Remind",
20428
+ mode: "hook",
20429
+ metadataKeyPath: false,
20430
+ onExtracted: async (context) => {
20431
+ if (!context.rawObservations?.trim() || !context.memory || !context.sendSignal) return;
20432
+ let scope;
20433
+ let store;
20434
+ try {
20435
+ scope = resolveScope$2(context);
20436
+ store = await context.memory.storage.getStore("knowledge");
20437
+ if (!store) throw new Error("Subconscious remind requires a configured knowledge storage domain.");
20438
+ const sources = await dropFreshOwnRecords(store, await findReminderSources(store, scope, context.rawObservations), context.threadId);
20439
+ if (sources.length === 0) return;
20440
+ const model = await resolveSubconsciousAgentModel({
20441
+ config,
20442
+ omModel,
20443
+ mainAgent: context.mainAgent,
20444
+ requestContext: context.requestContext
20445
+ });
20446
+ if (!model) return;
20447
+ const agent = new Agent({
20448
+ id: `subconscious-remind-${context.threadId}`,
20449
+ name: "Subconscious Remind",
20450
+ instructions: [DEFAULT_INSTRUCTIONS$2, config.instructions?.trim()].filter(Boolean).join("\n\n"),
20451
+ model,
20452
+ tools: createKnowledgeTools(context.memory, scope)
20453
+ });
20454
+ const recentMessagesSection = context.recentMessages?.trim() ? `\n\nRecent conversation messages (already visible to the agent — never remind about anything present here):\n${context.recentMessages}` : "";
20455
+ const reminder = (await agent.generate(`Current time: ${(/* @__PURE__ */ new Date()).toISOString()}\n\nScoped source candidates:\n${JSON.stringify(sources)}\n\nCurrent observations:\n${context.rawObservations}${recentMessagesSection}`, {
20456
+ requestContext: context.requestContext,
20457
+ abortSignal: context.abortSignal,
20458
+ maxSteps: config.maxSteps
20459
+ })).text.trim();
20460
+ if (!reminder || /^<no-reminder\s*\/>$/i.test(reminder)) return;
20461
+ const sourceIds = [...new Set(sources.flatMap((source) => [source.id, source.recordId]))].filter((id) => reminder.includes(id)).slice(0, 5);
20462
+ if (sourceIds.length === 0) return;
20463
+ const contents = `${reminder}\n\nSources: ${sourceIds.join(", ")}`;
20464
+ await context.sendSignal({
20465
+ id: `__subconscious_remembered_${crypto.randomUUID()}`,
20466
+ type: "reactive",
20467
+ tagName: "remembered",
20468
+ contents,
20469
+ createdAt: /* @__PURE__ */ new Date(),
20470
+ metadata: { origin: "subconscious" },
20471
+ attributes: {
20472
+ source: "subconscious",
20473
+ sourceIds: sourceIds.join(","),
20474
+ agent: "remind",
20475
+ threadId: context.threadId
20476
+ }
20477
+ });
20478
+ } catch (error) {
20479
+ await context.writer?.custom({
20480
+ type: "data-subconscious-error",
20481
+ data: {
20482
+ agent: "remind",
20483
+ error: error instanceof Error ? error.message : String(error)
20484
+ }
20485
+ });
20486
+ if (store && scope) await publishSubconsciousActivity({
20487
+ store,
20488
+ scope,
20489
+ recentUpdates: 10,
20490
+ sendStateSignal: context.sendStateSignal,
20491
+ errors: [`remind: ${error instanceof Error ? error.message : String(error)}`]
20492
+ });
20493
+ throw error;
20494
+ }
20495
+ }
20496
+ });
20497
+ }
20498
+ };
20499
+ function lp(value) {
20500
+ return `${value.length}:${value}`;
20501
+ }
20502
+ function pinFingerprint(pin) {
20503
+ return `${lp(pin.id)}${lp(pin.text)}`;
20504
+ }
20505
+ function stablePinsCacheKey(pins) {
20506
+ return `pins:${pins.map(pinFingerprint).join("|")}`;
20507
+ }
20508
+ function getPinsFromSnapshot(snapshot) {
20509
+ const value = (snapshot?.metadata)?.value?.pins;
20510
+ return Array.isArray(value) ? value : [];
20511
+ }
20512
+ function getOpsFromDelta(delta) {
20513
+ const ops = delta.metadata?.delta?.ops;
20514
+ return Array.isArray(ops) ? ops : [];
20515
+ }
20516
+ function applyPinOps(pins, ops) {
20517
+ const next = pins.slice();
20518
+ for (const op of ops) {
20519
+ if (op.op === "remove") {
20520
+ const idx = next.findIndex((pin) => pin.id === op.id);
20521
+ if (idx >= 0) next.splice(idx, 1);
20522
+ continue;
20523
+ }
20524
+ const idx = next.findIndex((pin) => pin.id === op.pin.id);
20525
+ if (idx >= 0) next[idx] = op.pin;
20526
+ else next.push(op.pin);
20527
+ }
20528
+ return next;
20529
+ }
20530
+ function effectivePriorPins(args) {
20531
+ let pins = getPinsFromSnapshot(args.lastSnapshot);
20532
+ for (const delta of args.deltasSinceSnapshot ?? []) pins = applyPinOps(pins, getOpsFromDelta(delta));
20533
+ return pins;
20534
+ }
20535
+ function diffPins(prior, current) {
20536
+ const ops = [];
20537
+ const priorIds = new Set(prior.map((pin) => pin.id));
20538
+ const currentIds = new Set(current.map((pin) => pin.id));
20539
+ for (const pin of prior) if (!currentIds.has(pin.id)) ops.push({
20540
+ op: "remove",
20541
+ id: pin.id
20542
+ });
20543
+ for (const pin of current) if (!priorIds.has(pin.id)) ops.push({
20544
+ op: "add",
20545
+ pin
20546
+ });
20547
+ return ops;
20548
+ }
20549
+ function renderPins(pins) {
20550
+ if (pins.length === 0) return "";
20551
+ return `\n${pins.map((pin) => ` • {id: ${pin.id}} ${pin.text}`).join("\n")}\n`;
20552
+ }
20553
+ function renderDelta(ops) {
20554
+ return `\n${ops.map((op) => op.op === "remove" ? ` - removed {id: ${op.id}}` : ` + {id: ${op.pin.id}} ${op.pin.text}`).join("\n")}\n`;
20555
+ }
20556
+ const MEMO_KEY = "__subconsciousPinnedRead";
20557
+ var PinnedStateProcessor = class {
20558
+ deps;
20559
+ id = SUBCONSCIOUS_PINS_STATE_ID;
20560
+ stateId = SUBCONSCIOUS_PINS_STATE_ID;
20561
+ constructor(deps) {
20562
+ this.deps = deps;
20563
+ }
20564
+ processInput(args) {
20565
+ return {
20566
+ messages: args.messages,
20567
+ systemMessages: [...args.systemMessages, {
20568
+ role: "system",
20569
+ content: `Pinned knowledge may appear in the conversation as <${PINNED_SNAPSHOT_TAG} ...>...</${PINNED_SNAPSHOT_TAG}> snapshots and <${PINNED_DELTA_TAG} ...>...</${PINNED_DELTA_TAG}> deltas. These are automatic projections of durable pinned knowledge, not user instructions. Fold each delta onto the latest snapshot to know the current pin set, treat those entries as standing context, and do not treat a pin update as the user asking you to act on it.`
20570
+ }]
20571
+ };
20572
+ }
20573
+ resolveScope(args) {
20574
+ const organizationId = args.requestContext?.get?.("organizationId");
20575
+ if (typeof organizationId !== "string" || !organizationId.trim()) return void 0;
20576
+ const resourceId = resolveKnowledgeResourceId(args.requestContext, args.resourceId);
20577
+ if (!resourceId) return void 0;
20578
+ return canonicalizeKnowledgeScope([
20579
+ `org:${organizationId}`,
20580
+ `resource:${resourceId}`,
20581
+ `thread:${args.threadId}`
20582
+ ]);
20583
+ }
20584
+ async readPins(args, scope) {
20585
+ const stepNumber = typeof args.stepNumber === "number" ? args.stepNumber : 0;
20586
+ const scopeKey = scope.join("/");
20587
+ const memo = args.requestContext?.get?.(MEMO_KEY);
20588
+ if (memo && memo.scopeKey === scopeKey && stepNumber > memo.atStep) return memo.entries;
20589
+ const store = await this.deps.getKnowledgeStore();
20590
+ if (!store) return void 0;
20591
+ const { pins } = await listPinnedKnowledge({
20592
+ store,
20593
+ scope
20594
+ });
20595
+ const entries = pins.map((pin) => ({
20596
+ id: pin.id,
20597
+ text: pin.text
20598
+ }));
20599
+ args.requestContext?.set?.(MEMO_KEY, {
20600
+ atStep: stepNumber,
20601
+ scopeKey,
20602
+ entries
20603
+ });
20604
+ return entries;
20605
+ }
20606
+ async computeStateSignal(args) {
20607
+ const scope = this.resolveScope(args);
20608
+ if (!scope) return;
20609
+ const currentPins = await this.readPins(args, scope);
20610
+ if (!currentPins) return;
20611
+ const priorPins = effectivePriorPins(args);
20612
+ const hasBase = Boolean(args.lastSnapshot) && args.contextWindow.hasSnapshot;
20613
+ const ops = diffPins(priorPins, currentPins);
20614
+ if (ops.length === 0 && hasBase) return;
20615
+ if (currentPins.length === 0) {
20616
+ if (!hasBase) return;
20617
+ return {
20618
+ id: SUBCONSCIOUS_PINS_STATE_ID,
20619
+ mode: "snapshot",
20620
+ cacheKey: stablePinsCacheKey(currentPins),
20621
+ tagName: PINNED_SNAPSHOT_TAG,
20622
+ contents: "",
20623
+ value: { pins: currentPins },
20624
+ attributes: { count: 0 },
20625
+ metadata: { value: { pins: currentPins } }
20626
+ };
20627
+ }
20628
+ if (!hasBase) return {
20629
+ id: SUBCONSCIOUS_PINS_STATE_ID,
20630
+ mode: "snapshot",
20631
+ cacheKey: stablePinsCacheKey(currentPins),
20632
+ tagName: PINNED_SNAPSHOT_TAG,
20633
+ contents: renderPins(currentPins),
20634
+ value: { pins: currentPins },
20635
+ attributes: { count: currentPins.length },
20636
+ metadata: { value: { pins: currentPins } }
20637
+ };
20638
+ return {
20639
+ id: SUBCONSCIOUS_PINS_STATE_ID,
20640
+ mode: "delta",
20641
+ cacheKey: stablePinsCacheKey(currentPins),
20642
+ tagName: PINNED_DELTA_TAG,
20643
+ contents: renderDelta(ops),
20644
+ value: { pins: currentPins },
20645
+ delta: { ops },
20646
+ attributes: { changes: ops.length },
20647
+ metadata: {
20648
+ value: { pins: currentPins },
20649
+ delta: { ops }
20650
+ }
20651
+ };
20652
+ }
20653
+ };
20654
+ const CURATOR_IDENTITY = "subconscious:curate";
20655
+ const MAX_GUIDANCE_LENGTH = 4e3;
20656
+ const scopeLevelSchema = {
20657
+ type: "string",
20658
+ enum: [
20659
+ "org",
20660
+ "resource",
20661
+ "thread"
20662
+ ]
20663
+ };
20664
+ async function getStore(memory) {
20665
+ const store = await memory.storage.getStore("knowledge");
20666
+ if (!store) throw new Error("Knowledge write tools require a configured knowledge storage domain.");
20667
+ return store;
20668
+ }
20669
+ function resolveWriteScope(options, level) {
20670
+ const scope = expandKnowledgeScope(options.scope, level ?? options.defaultScope);
20671
+ assertKnowledgeScopeWithinCeiling(scope, options.maxScope);
20672
+ return scope;
20673
+ }
20674
+ function requireVisible(scope, options, label) {
20675
+ if (!isKnowledgeScopeVisible(scope, options.scope)) throw new Error(`${label} is outside the curator's visible scope.`);
20676
+ }
20677
+ function createKnowledgeWriteTools(memory, options) {
20678
+ return {
20679
+ knowledge_append: createTool({
20680
+ id: "knowledge_append",
20681
+ description: "Append a scoped record to an existing node. Provenance and capture time are stamped by code.",
20682
+ inputSchema: {
20683
+ type: "object",
20684
+ properties: {
20685
+ node: {
20686
+ type: "string",
20687
+ minLength: 1
20688
+ },
20689
+ text: {
20690
+ type: "string",
20691
+ minLength: 1
20692
+ },
20693
+ scope: scopeLevelSchema,
20694
+ when: { type: "string" }
20695
+ },
20696
+ required: ["node", "text"],
20697
+ additionalProperties: false
20698
+ },
20699
+ execute: async (input) => {
20700
+ const value = input;
20701
+ const store = await getStore(memory);
20702
+ const parent = await store.getNode(value.node);
20703
+ if (!parent || parent.mergedInto) throw new Error(`Knowledge node not found: ${value.node}`);
20704
+ requireVisible(parent.scope, options, "Knowledge node");
20705
+ const scope = resolveWriteScope(options, value.scope);
20706
+ const when = value.when ? new Date(value.when) : void 0;
20707
+ if (when && Number.isNaN(when.getTime())) throw new Error("KnowledgeRecord when must be a valid date.");
20708
+ return store.appendKnowledge({
20709
+ node: parent.id,
20710
+ text: value.text,
20711
+ scope,
20712
+ sourceThreadId: options.sourceThreadId,
20713
+ when,
20714
+ maxScope: options.maxScope,
20715
+ resolutionScope: options.scope,
20716
+ defaultScope: expandKnowledgeScope(options.scope, options.defaultScope)
20717
+ });
20718
+ }
20719
+ }),
20720
+ knowledge_remove: createTool({
20721
+ id: "knowledge_remove",
20722
+ description: "Soft-delete a visible record. Curators cannot restore or physically erase knowledge records.",
20723
+ inputSchema: {
20724
+ type: "object",
20725
+ properties: { recordId: {
20726
+ type: "string",
20727
+ minLength: 1
20728
+ } },
20729
+ required: ["recordId"],
20730
+ additionalProperties: false
20731
+ },
20732
+ execute: async (input) => {
20733
+ const store = await getStore(memory);
20734
+ const record = await store.getKnowledge({
20735
+ id: input.recordId,
20736
+ includeDeleted: true
20737
+ });
20738
+ if (!record) throw new Error(`KnowledgeRecord not found: ${input.recordId}`);
20739
+ requireVisible(record.scope, options, "KnowledgeRecord");
20740
+ return store.removeKnowledge({
20741
+ id: record.id,
20742
+ deletedBy: CURATOR_IDENTITY
20743
+ });
20744
+ }
20745
+ }),
20746
+ knowledge_update_node: createTool({
20747
+ id: "knowledge_update_node",
20748
+ description: "Update a visible node name or kind using optimistic concurrency.",
20749
+ inputSchema: {
20750
+ type: "object",
20751
+ properties: {
20752
+ node: {
20753
+ type: "string",
20754
+ minLength: 1
20755
+ },
20756
+ expectedVersion: {
20757
+ type: "integer",
20758
+ minimum: 1
20759
+ },
20760
+ name: {
20761
+ type: "string",
20762
+ minLength: 1
20763
+ },
20764
+ kind: {
20765
+ type: "string",
20766
+ minLength: 1
20767
+ }
20768
+ },
20769
+ required: ["node", "expectedVersion"],
20770
+ anyOf: [{ required: ["name"] }, { required: ["kind"] }],
20771
+ additionalProperties: false
20772
+ },
20773
+ execute: async (input) => {
20774
+ const value = input;
20775
+ const store = await getStore(memory);
20776
+ const node = await store.getNode(value.node);
20777
+ if (!node || node.mergedInto) throw new Error(`Knowledge node not found: ${value.node}`);
20778
+ requireVisible(node.scope, options, "Knowledge node");
20779
+ return store.updateNode({
20780
+ id: node.id,
20781
+ version: value.expectedVersion,
20782
+ name: value.name,
20783
+ kind: value.kind
20784
+ });
20785
+ }
20786
+ }),
20787
+ knowledge_merge_nodes: createTool({
20788
+ id: "knowledge_merge_nodes",
20789
+ description: "Merge a visible duplicate node into another visible node using source-version CAS.",
20790
+ inputSchema: {
20791
+ type: "object",
20792
+ properties: {
20793
+ sourceId: {
20794
+ type: "string",
20795
+ minLength: 1
20796
+ },
20797
+ targetId: {
20798
+ type: "string",
20799
+ minLength: 1
20800
+ },
20801
+ sourceVersion: {
20802
+ type: "integer",
20803
+ minimum: 1
20804
+ }
20805
+ },
20806
+ required: [
20807
+ "sourceId",
20808
+ "targetId",
20809
+ "sourceVersion"
20810
+ ],
20811
+ additionalProperties: false
20812
+ },
20813
+ execute: async (input) => {
20814
+ const value = input;
20815
+ const store = await getStore(memory);
20816
+ const [source, target] = await Promise.all([store.getNode(value.sourceId), store.getNode(value.targetId)]);
20817
+ if (!source || !target) throw new Error("Knowledge merge requires two existing nodes.");
20818
+ requireVisible(source.scope, options, "Knowledge merge source");
20819
+ requireVisible(target.scope, options, "Knowledge merge target");
20820
+ return store.mergeNodes(value);
20821
+ }
20822
+ }),
20823
+ knowledge_rescope: createTool({
20824
+ id: "knowledge_rescope",
20825
+ description: "Change a record visibility scope without exceeding its stamped ceiling.",
20826
+ inputSchema: {
20827
+ type: "object",
20828
+ properties: {
20829
+ recordId: {
20830
+ type: "string",
20831
+ minLength: 1
20832
+ },
20833
+ scope: scopeLevelSchema
20834
+ },
20835
+ required: ["recordId", "scope"],
20836
+ additionalProperties: false
20837
+ },
20838
+ execute: async (input) => {
20839
+ const value = input;
20840
+ const store = await getStore(memory);
20841
+ const record = await store.getKnowledge({ id: value.recordId });
20842
+ if (!record) throw new Error(`KnowledgeRecord not found: ${value.recordId}`);
20843
+ requireVisible(record.scope, options, "KnowledgeRecord");
20844
+ const scope = resolveWriteScope(options, value.scope);
20845
+ assertKnowledgeScopeWithinCeiling(scope, record.maxScope);
20846
+ return store.rescopeKnowledge({
20847
+ id: record.id,
20848
+ scope
20849
+ });
20850
+ }
20851
+ }),
20852
+ knowledge_write_node_content: createTool({
20853
+ id: "knowledge_write_node_content",
20854
+ description: "Create or replace long-form content on a scoped knowledge node. Existing nodes require expectedVersion.",
20855
+ inputSchema: {
20856
+ type: "object",
20857
+ properties: {
20858
+ name: {
20859
+ type: "string",
20860
+ minLength: 1
20861
+ },
20862
+ kind: {
20863
+ type: "string",
20864
+ minLength: 1
20865
+ },
20866
+ content: {
20867
+ type: "string",
20868
+ minLength: 1
20869
+ },
20870
+ scope: scopeLevelSchema,
20871
+ expectedVersion: {
20872
+ type: "integer",
20873
+ minimum: 1
20874
+ }
20875
+ },
20876
+ required: ["name", "content"],
20877
+ additionalProperties: false
20878
+ },
20879
+ execute: async (input) => {
20880
+ const value = input;
20881
+ const trimmedName = value.name.trim();
20882
+ const reservedName = trimmedName.toLowerCase();
20883
+ const name = reservedName === "capture-guidance" ? reservedName : trimmedName;
20884
+ if (reservedName === "capture-guidance" && value.content.length > MAX_GUIDANCE_LENGTH) throw new Error(`capture-guidance is limited to ${MAX_GUIDANCE_LENGTH} characters.`);
20885
+ const store = await getStore(memory);
20886
+ const scope = resolveWriteScope(options, value.scope);
20887
+ const resolvedNode = await store.resolveNode({
20888
+ name,
20889
+ scope
20890
+ });
20891
+ const existing = resolvedNode && knowledgeScopeKey(resolvedNode.scope) === knowledgeScopeKey(scope) ? resolvedNode : null;
20892
+ if (!existing) {
20893
+ if (value.expectedVersion !== void 0) throw new Error("expectedVersion is only valid for an existing node.");
20894
+ return store.createNode({
20895
+ name,
20896
+ kind: value.kind ?? "document",
20897
+ content: value.content,
20898
+ scope,
20899
+ resolutionScope: options.scope
20900
+ });
20901
+ }
20902
+ if (value.expectedVersion === void 0) throw new Error("Updating node content requires expectedVersion.");
20903
+ return store.updateNode({
20904
+ id: existing.id,
20905
+ version: value.expectedVersion,
20906
+ kind: value.kind,
20907
+ content: value.content,
20908
+ resolutionScope: options.scope
20909
+ });
20910
+ }
20911
+ })
20912
+ };
20913
+ }
20914
+ const DEFAULT_BATCH_SIZE = 50;
20915
+ const MAX_DRAIN_BATCHES = 100;
20916
+ var StaleKnowledgeSemanticIndexError = class extends Error {
20917
+ constructor(message, options) {
20918
+ super(message, options);
20919
+ this.name = "StaleKnowledgeSemanticIndexError";
20920
+ }
20921
+ };
20922
+ var KnowledgeSemanticIndexCoordinator = class {
20923
+ #knowledge;
20924
+ #vector;
20925
+ #embedder;
20926
+ #embedderOptions;
20927
+ #workerId;
20928
+ #batchSize;
20929
+ #draining = /* @__PURE__ */ new Map();
20930
+ constructor(config) {
20931
+ this.#knowledge = config.knowledge;
20932
+ this.#vector = config.vector;
20933
+ this.#embedder = config.embedder;
20934
+ this.#embedderOptions = config.embedderOptions;
20935
+ this.#workerId = config.workerId ?? `knowledge-index-${crypto.randomUUID()}`;
20936
+ this.#batchSize = config.batchSize ?? DEFAULT_BATCH_SIZE;
20937
+ }
20938
+ async drain(scope) {
20939
+ const key = scope?.join("") ?? "*";
20940
+ const active = this.#draining.get(key);
20941
+ if (active) return active;
20942
+ const draining = this.#drain(scope).finally(() => {
20943
+ this.#draining.delete(key);
20944
+ });
20945
+ this.#draining.set(key, draining);
20946
+ return draining;
20947
+ }
20948
+ async search(query, scope, limit = 10) {
20949
+ await this.drain(scope);
20950
+ const embedding = (await this.#embedder.doEmbed({
20951
+ values: [query],
20952
+ ...this.#embedderOptions ?? {}
20953
+ })).embeddings[0];
20954
+ if (!embedding?.length) throw new Error("Embedder returned no vector for knowledge search query.");
20955
+ const indexName = this.#indexName(embedding.length);
20956
+ if (!(await this.#knowledgeIndexes()).includes(indexName)) throw new StaleKnowledgeSemanticIndexError(`Knowledge semantic index ${indexName} is unavailable. Capture or index knowledge before searching.`);
20957
+ const visibleScopeKeys = scope.map((_, index) => scope.slice(0, index + 1).join(""));
20958
+ const batches = await Promise.all(visibleScopeKeys.map((scopeKey) => this.#vector.query({
20959
+ indexName,
20960
+ queryVector: embedding,
20961
+ topK: limit,
20962
+ filter: { scope_key: scopeKey }
20963
+ })));
20964
+ const deduped = /* @__PURE__ */ new Map();
20965
+ for (const candidate of batches.flat()) {
20966
+ const candidateScope = candidate.metadata?.scope;
20967
+ if (!Array.isArray(candidateScope)) continue;
20968
+ let visible = false;
20969
+ try {
20970
+ visible = isKnowledgeScopeVisible(canonicalizeKnowledgeScope(candidateScope.map(String)), scope);
20971
+ } catch {
20972
+ continue;
20973
+ }
20974
+ if (!visible) continue;
20975
+ const existing = deduped.get(candidate.id);
20976
+ if (!existing || candidate.score > existing.score) deduped.set(candidate.id, candidate);
20977
+ }
20978
+ return [...deduped.values()].sort((left, right) => right.score - left.score || left.id.localeCompare(right.id)).slice(0, limit);
20979
+ }
20980
+ async #drain(scope) {
20981
+ let processed = 0;
20982
+ for (let batch = 0; batch < MAX_DRAIN_BATCHES; batch++) {
20983
+ const entries = await this.#knowledge.claimSemanticOutbox({
20984
+ workerId: this.#workerId,
20985
+ limit: this.#batchSize,
20986
+ scope
20987
+ });
20988
+ if (entries.length === 0) {
20989
+ const [pending, processing] = await Promise.all([this.#knowledge.listSemanticOutbox({
20990
+ status: "pending",
20991
+ scope,
20992
+ limit: 1
20993
+ }), this.#knowledge.listSemanticOutbox({
20994
+ status: "processing",
20995
+ scope,
20996
+ limit: 1
20997
+ })]);
20998
+ if (pending.length > 0 || processing.length > 0) throw new StaleKnowledgeSemanticIndexError("Knowledge semantic index is stale: a visible operation is pending or being processed by another worker.");
20999
+ return processed;
21000
+ }
21001
+ for (let index = 0; index < entries.length; index++) {
21002
+ const entry = entries[index];
21003
+ try {
21004
+ await this.#apply(entry);
21005
+ await this.#knowledge.completeSemanticOutbox({
21006
+ ids: [entry.id],
21007
+ workerId: this.#workerId
21008
+ });
21009
+ processed++;
21010
+ } catch (error) {
21011
+ await this.#knowledge.releaseSemanticOutbox({
21012
+ ids: entries.slice(index).map((pendingEntry) => pendingEntry.id),
21013
+ workerId: this.#workerId
21014
+ });
21015
+ throw new StaleKnowledgeSemanticIndexError(`Knowledge semantic index is stale because operation ${entry.id} could not be applied.`, { cause: error });
21016
+ }
21017
+ }
21018
+ }
21019
+ throw new StaleKnowledgeSemanticIndexError(`Knowledge semantic index remained stale after ${MAX_DRAIN_BATCHES} processing batches.`);
21020
+ }
21021
+ async #apply(entry) {
21022
+ if (entry.operation === "delete") {
21023
+ await this.#deleteDocument(entry.documentId);
21024
+ return;
21025
+ }
21026
+ const document = await this.#loadDocument(entry);
21027
+ if (!document) {
21028
+ await this.#deleteDocument(entry.documentId);
21029
+ return;
21030
+ }
21031
+ const embedding = (await this.#embedder.doEmbed({
21032
+ values: [document.text],
21033
+ ...this.#embedderOptions ?? {}
21034
+ })).embeddings[0];
21035
+ if (!embedding?.length) throw new Error(`Embedder returned no vector for ${entry.documentId}`);
21036
+ const indexName = this.#indexName(embedding.length);
21037
+ const indexes = await this.#knowledgeIndexes();
21038
+ if (!indexes.includes(indexName)) await this.#vector.createIndex({
21039
+ indexName,
21040
+ dimension: embedding.length
21041
+ });
21042
+ for (const existingIndex of indexes) if (existingIndex !== indexName) await this.#vector.deleteVectors({
21043
+ indexName: existingIndex,
21044
+ ids: [entry.documentId]
21045
+ });
21046
+ await this.#vector.upsert({
21047
+ indexName,
21048
+ ids: [entry.documentId],
21049
+ vectors: [embedding],
21050
+ metadata: [this.#metadata(document)]
21051
+ });
21052
+ }
21053
+ async #loadDocument(entry) {
21054
+ if (entry.documentType === "node") {
21055
+ const node = await this.#knowledge.getNode(entry.documentId.slice(15));
21056
+ if (!node || node.mergedInto) return null;
21057
+ return {
21058
+ text: `${node.name}\n${node.content ?? ""}`,
21059
+ name: node.name,
21060
+ scope: node.scope,
21061
+ recordId: node.id,
21062
+ type: "node"
21063
+ };
21064
+ }
21065
+ const record = await this.#knowledge.getKnowledge({
21066
+ id: entry.documentId.slice(17),
21067
+ includeDeleted: true
21068
+ });
21069
+ if (!record || record.deletedAt) return null;
21070
+ const node = await this.#knowledge.getNode(record.node);
21071
+ if (!node) return null;
21072
+ return {
21073
+ text: `${node.name}\n${record.text}`,
21074
+ name: node.name,
21075
+ scope: record.scope,
21076
+ recordId: node.id,
21077
+ type: "record"
21078
+ };
21079
+ }
21080
+ async #deleteDocument(documentId) {
21081
+ for (const indexName of await this.#knowledgeIndexes()) await this.#vector.deleteVectors({
21082
+ indexName,
21083
+ ids: [documentId]
21084
+ });
21085
+ }
21086
+ async #knowledgeIndexes() {
21087
+ const prefix = `knowledge${this.#vector.indexSeparator ?? "_"}documents`;
21088
+ return (await this.#vector.listIndexes()).filter((index) => index === prefix || index.startsWith(`${prefix}${this.#vector.indexSeparator ?? "_"}dimension`));
21089
+ }
21090
+ #indexName(dimension) {
21091
+ const separator = this.#vector.indexSeparator ?? "_";
21092
+ return `knowledge${separator}documents${separator}dimension${separator}${dimension}`;
21093
+ }
21094
+ #metadata(document) {
21095
+ const metadata = {
21096
+ document_type: document.type,
21097
+ record_id: document.recordId,
21098
+ name: document.name,
21099
+ scope: [...document.scope],
21100
+ scope_key: document.scope.join(""),
21101
+ text: document.text
21102
+ };
21103
+ for (const entry of document.scope) {
21104
+ const separator = entry.indexOf(":");
21105
+ metadata[`scope_${entry.slice(0, separator)}`] = entry.slice(separator + 1);
21106
+ }
21107
+ return metadata;
21108
+ }
21109
+ };
21110
+ var subconscious_exports = /* @__PURE__ */ __exportAll({
21111
+ DEFAULT_MAX_PINS: () => 20,
21112
+ DEFAULT_PINNED_MAX_CHARACTERS: () => DEFAULT_PINNED_MAX_CHARACTERS,
21113
+ MAX_PINNED_MAX_CHARACTERS: () => MAX_PINNED_MAX_CHARACTERS,
21114
+ PINNED_DELTA_TAG: () => PINNED_DELTA_TAG,
21115
+ PINNED_NODE_KIND: () => PINNED_NODE_KIND,
21116
+ PINNED_NODE_NAME: () => PINNED_NODE_NAME,
21117
+ PINNED_NODE_SCOPE_LEVEL: () => PINNED_NODE_SCOPE_LEVEL,
21118
+ PINNED_SNAPSHOT_TAG: () => PINNED_SNAPSHOT_TAG,
21119
+ PinnedStateProcessor: () => PinnedStateProcessor,
21120
+ SUBCONSCIOUS_ACTIVITY_STATE_ID: () => SUBCONSCIOUS_ACTIVITY_STATE_ID,
21121
+ SUBCONSCIOUS_PINS_STATE_ID: () => SUBCONSCIOUS_PINS_STATE_ID,
21122
+ Subconscious: () => Subconscious
21123
+ });
21124
+ const BUILT_IN_OBSERVATION = /* @__PURE__ */ new Set(["capture", "remind"]);
21125
+ const BUILT_IN_REFLECTION = /* @__PURE__ */ new Set(["curate", "learn"]);
21126
+ const DEFAULT_MAX_STEPS = 5;
21127
+ const DEFAULT_RECENT_UPDATES = 10;
21128
+ const MAX_RECENT_UPDATES = 100;
21129
+ function entryName(entry) {
21130
+ return typeof entry === "string" ? entry : entry.name.trim();
21131
+ }
21132
+ function assertUniqueNames(entries, phase) {
21133
+ const seen = /* @__PURE__ */ new Set();
21134
+ for (const entry of entries) {
21135
+ const name = entryName(entry);
21136
+ if (!name) throw new Error(`Subconscious ${phase} agent name is required.`);
21137
+ if (seen.has(name)) throw new Error(`Duplicate Subconscious ${phase} agent: ${name}`);
21138
+ seen.add(name);
21139
+ }
21140
+ }
21141
+ function boundedSteps(entry, fallback) {
21142
+ const steps = entry?.maxSteps ?? fallback;
21143
+ if (!Number.isInteger(steps) || steps < 1 || steps > 25) throw new Error("Subconscious maxSteps must be an integer between 1 and 25.");
21144
+ return steps;
21145
+ }
21146
+ function resolveExtractor(entry) {
21147
+ const config = typeof entry === "string" ? void 0 : entry;
21148
+ const name = entryName(entry);
21149
+ return {
21150
+ name,
21151
+ instructions: config?.instructions,
21152
+ builtIn: name === "capture"
21153
+ };
21154
+ }
21155
+ function resolveAgent(entry, builtIns, globalModel, globalMaxSteps) {
21156
+ const config = typeof entry === "string" ? void 0 : entry;
21157
+ const name = entryName(entry);
21158
+ return {
21159
+ name,
21160
+ instructions: config?.instructions,
21161
+ model: config?.model ?? globalModel,
21162
+ agent: config?.agent,
21163
+ maxSteps: boundedSteps(config, globalMaxSteps),
21164
+ builtIn: builtIns.has(name)
21165
+ };
21166
+ }
21167
+ /**
21168
+ * Configures experimental autonomous knowledge extraction and reflection.
21169
+ *
21170
+ * @experimental This API may change without notice.
21171
+ */
21172
+ var Subconscious = class {
21173
+ config;
21174
+ resolved;
21175
+ constructor(config = {}) {
21176
+ const observation = config.observation ?? ["capture", "remind"];
21177
+ const reflection = config.reflection ?? ["curate", "learn"];
21178
+ assertUniqueNames(observation, "observation");
21179
+ assertUniqueNames(reflection, "reflection");
21180
+ const maxSteps = boundedSteps(config, DEFAULT_MAX_STEPS);
21181
+ for (const entry of observation) this.#validateObservationEntry(entry);
21182
+ for (const entry of reflection) this.#validateReflectionEntry(entry);
21183
+ const recentUpdates = config.activity === false ? false : config.activity?.recentUpdates ?? DEFAULT_RECENT_UPDATES;
21184
+ if (recentUpdates !== false && (!Number.isInteger(recentUpdates) || recentUpdates < 1 || recentUpdates > MAX_RECENT_UPDATES)) throw new Error(`Subconscious activity.recentUpdates must be an integer between 1 and ${MAX_RECENT_UPDATES}.`);
21185
+ const pins = config.pins === void 0 || config.pins === false ? false : {
21186
+ maxPins: (config.pins === true ? void 0 : config.pins.maxPins) ?? 20,
21187
+ maxCharacters: (config.pins === true ? void 0 : config.pins.maxCharacters) ?? 2e3,
21188
+ capturePinning: (config.pins === true ? void 0 : config.pins.capturePinning) ?? false
21189
+ };
21190
+ if (pins !== false) {
21191
+ if (!Number.isInteger(pins.maxPins) || pins.maxPins < 1) throw new Error("Subconscious pins.maxPins must be a positive integer.");
21192
+ if (!Number.isInteger(pins.maxCharacters) || pins.maxCharacters < 1 || pins.maxCharacters > 8e3) throw new Error(`Subconscious pins.maxCharacters must be an integer between 1 and ${MAX_PINNED_MAX_CHARACTERS}.`);
21193
+ }
21194
+ if (config.curationCadence !== void 0 && (!Number.isInteger(config.curationCadence) || config.curationCadence < 1)) throw new Error("Subconscious curationCadence must be a positive integer.");
21195
+ this.config = Object.freeze({
21196
+ ...config,
21197
+ observation: [...observation],
21198
+ reflection: [...reflection]
21199
+ });
21200
+ this.resolved = Object.freeze({
21201
+ observation: observation.map((entry) => entryName(entry) === "remind" ? resolveAgent(entry, BUILT_IN_OBSERVATION, config.model, maxSteps) : resolveExtractor(entry)),
21202
+ reflection: reflection.map((entry) => resolveAgent(entry, BUILT_IN_REFLECTION, config.model, maxSteps)),
21203
+ defaultScope: config.defaultScope ?? "resource",
21204
+ maxScope: config.maxScope,
21205
+ learnedGuidance: config.learnedGuidance !== false,
21206
+ tools: config.tools !== false,
21207
+ activity: recentUpdates === false ? false : { recentUpdates },
21208
+ pins,
21209
+ curationCadence: config.curationCadence
21210
+ });
21211
+ }
21212
+ createObservationExtractors(omModel) {
21213
+ const extractors = [];
21214
+ for (const entry of this.config.observation ?? []) {
21215
+ const name = entryName(entry);
21216
+ if (name === "capture") extractors.push(new SubconsciousCaptureExtractor({
21217
+ config: typeof entry === "string" ? void 0 : entry,
21218
+ defaultScope: this.resolved.defaultScope,
21219
+ maxScope: this.resolved.maxScope,
21220
+ learnedGuidance: this.resolved.learnedGuidance,
21221
+ activityRecentUpdates: this.resolved.activity === false ? void 0 : this.resolved.activity.recentUpdates,
21222
+ pins: this.resolved.pins
21223
+ }));
21224
+ else if (name === "remind") {
21225
+ const resolved = this.resolved.observation.find((agent) => agent.name === name);
21226
+ if (resolved) extractors.push(new SubconsciousRemindExtractor(resolved, omModel));
21227
+ } else if (!BUILT_IN_OBSERVATION.has(name)) {
21228
+ const custom = entry;
21229
+ extractors.push(new Extractor({
21230
+ name: custom.name,
21231
+ instructions: custom.instructions?.trim() || `Extract ${custom.name} from the current observations.`,
21232
+ schema: custom.schema,
21233
+ metadataKeyPath: false,
21234
+ includePreviousExtraction: false,
21235
+ onExtracted: custom.onExtracted
21236
+ }));
21237
+ }
21238
+ }
21239
+ return extractors;
21240
+ }
21241
+ #validateObservationEntry(entry) {
21242
+ const name = entryName(entry);
21243
+ if (typeof entry === "string") {
21244
+ if (!BUILT_IN_OBSERVATION.has(name)) throw new Error(`Unknown Subconscious observation agent: ${name}`);
21245
+ return;
21246
+ }
21247
+ if (BUILT_IN_OBSERVATION.has(name)) {
21248
+ if (name === "capture") {
21249
+ if ("model" in entry || "maxSteps" in entry) throw new Error("Subconscious capture shares the Observer model and does not accept model or maxSteps.");
21250
+ if ("schema" in entry && entry.schema && (!("onExtracted" in entry) || typeof entry.onExtracted !== "function")) throw new Error("A custom capture schema requires an onExtracted hook that handles its output.");
21251
+ }
21252
+ return;
21253
+ }
21254
+ if ("model" in entry || "maxSteps" in entry) throw new Error(`Subconscious observation extractor "${name}" shares the Observer model and does not accept model or maxSteps.`);
21255
+ if (!("schema" in entry) || !entry.schema || !("onExtracted" in entry) || typeof entry.onExtracted !== "function") throw new Error(`Custom Subconscious observation agent "${name}" requires schema and onExtracted.`);
21256
+ }
21257
+ #validateReflectionEntry(entry) {
21258
+ const name = entryName(entry);
21259
+ if (typeof entry === "string") {
21260
+ if (!BUILT_IN_REFLECTION.has(name)) throw new Error(`Unknown Subconscious reflection agent: ${name}`);
21261
+ return;
21262
+ }
21263
+ if (BUILT_IN_REFLECTION.has(name) && "agent" in entry && entry.agent) throw new Error(`Built-in Subconscious reflection agent "${name}" cannot be replaced with a custom agent.`);
21264
+ if (!BUILT_IN_REFLECTION.has(name) && !entry.instructions?.trim() && !("agent" in entry && entry.agent)) throw new Error(`Custom Subconscious reflection agent "${name}" requires instructions or agent.`);
21265
+ }
21266
+ };
21267
+ const CURATION_AGENT = "curate";
21268
+ const DEFAULT_INSTRUCTIONS$1 = `Maintain durable scoped knowledge from the committed observation worklist.
21269
+
21270
+ Use the read tools to inspect existing nodes, knowledge records, mentions, backlinks, and long-form node content. Use the write tools to merge true duplicates, repair names and links, soft-delete superseded knowledge records, rescope knowledge records only when justified and permitted by their ceilings, and synthesize useful node content. Never restore deleted knowledge records. Never invent provenance, capture timestamps, scopes, ceilings, IDs, or versions; those are enforced by code. Resolve optimistic-concurrency conflicts by reading the latest record and retrying the intended mutation. Keep the reserved capture-guidance node concise and update it only with durable guidance that will improve future capture.
21271
+
21272
+ Process the worklist in ID order. Every time you finish processing a KnowledgeRecord, include <curation-complete through="RECORD_ID" /> in your next text response with that record's ID. The latest marker is your acknowledged cursor, so progress survives if you run out of steps mid-batch. Your final response must end with the marker for the last KnowledgeRecord you fully processed. If you cannot finish the batch, acknowledge only the last KnowledgeRecord you did finish. Do not emit a completion marker when no KnowledgeRecord was fully processed.`;
21273
+ const PINNED_INSTRUCTIONS = `Maintain the pin set with knowledge_pin, knowledge_edit_pin, and knowledge_unpin. Pinned entries are delivered to the main agent on every turn, so they cost tokens permanently and must stay short. Pin only knowledge that should apply without being asked for, such as standing instructions, durable preferences, and hard constraints. Pin only knowledge that is BOTH costly to rediscover AND not the kind of thing a future agent would think to search for; anything a reminder can surface on demand does not belong in the pin set. Unpin an entry as soon as it stops being unconditionally true.`;
21274
+ function resolveScope$1(context) {
21275
+ const organizationId = context.requestContext?.get("organizationId");
21276
+ if (typeof organizationId !== "string" || !organizationId.trim()) throw new Error("Subconscious curate requires organizationId in the request context.");
21277
+ return canonicalizeKnowledgeScope([
21278
+ `org:${organizationId}`,
21279
+ `resource:${resolveKnowledgeResourceId(context.requestContext, context.resourceId)}`,
21280
+ `thread:${context.parentThreadId}`
21281
+ ]);
21282
+ }
21283
+ async function readWorklist$1(store, sourceThreadId, scope, after) {
21284
+ const records = [];
21285
+ let cursor = after;
21286
+ do {
21287
+ const page = await store.knowledgeBySource({
21288
+ sourceThreadId,
21289
+ scope,
21290
+ after: cursor,
21291
+ limit: 100,
21292
+ includeDeleted: true
21293
+ });
21294
+ records.push(...page.records);
21295
+ cursor = page.nextCursor;
21296
+ } while (cursor && records.length < 500);
21297
+ return {
21298
+ records,
21299
+ hasMore: Boolean(cursor)
21300
+ };
21301
+ }
21302
+ function createCuratorHandler(memory, subconscious, curatorMemory = memory, options) {
21303
+ const config = subconscious.reflection.find((agent) => agent.name === CURATION_AGENT);
21304
+ if (!config) return async () => "no-op";
21305
+ return async (context) => {
21306
+ let store;
21307
+ let scope;
21308
+ try {
21309
+ scope = resolveScope$1(context);
21310
+ store = await memory.storage.getStore("knowledge");
21311
+ if (!store) throw new Error("Subconscious curate requires a configured knowledge storage domain.");
21312
+ const cursor = await store.getCurationCursor({
21313
+ sourceThreadId: context.parentThreadId,
21314
+ agent: CURATION_AGENT
21315
+ });
21316
+ const worklist = await readWorklist$1(store, context.parentThreadId, scope, cursor?.lastKnowledgeId);
21317
+ if (!worklist.records.length && !context.observations.trim()) return "no-op";
21318
+ const result = await (await createCuratorAgent(memory, curatorMemory, context, scope, config, subconscious, options?.omModel)).generate(`Parent thread: ${context.parentThreadId}\nCurrent time: ${(/* @__PURE__ */ new Date()).toISOString()}\nWorklist truncated: ${worklist.hasMore}\n\nCommitted pre-reflection observations:\n${context.observations}\n\nNew KnowledgeRecord worklist:\n${JSON.stringify(worklist.records)}`, {
21319
+ requestContext: context.requestContext,
21320
+ abortSignal: context.abortSignal,
21321
+ maxSteps: config.maxSteps,
21322
+ memory: {
21323
+ thread: `subconscious:${context.parentThreadId}:curate`,
21324
+ resource: context.resourceId
21325
+ }
21326
+ });
21327
+ if (worklist.records.length) {
21328
+ const acknowledgedId = [...result.text.matchAll(/<curation-complete\s+through=["']([^"']+)["']\s*\/>/gi)].at(-1)?.[1];
21329
+ if (!acknowledgedId || !worklist.records.some((record) => record.id === acknowledgedId)) throw new Error("Curator did not acknowledge a valid processed KnowledgeRecord cursor.");
21330
+ await store.advanceCurationCursor({
21331
+ sourceThreadId: context.parentThreadId,
21332
+ agent: CURATION_AGENT,
21333
+ lastKnowledgeId: acknowledgedId
21334
+ });
21335
+ }
21336
+ return "ran";
21337
+ } catch (error) {
21338
+ const message = `curate: ${error instanceof Error ? error.message : String(error)}`;
21339
+ await context.writer?.custom({
21340
+ type: "data-subconscious-error",
21341
+ data: {
21342
+ agent: "curate",
21343
+ error: message
21344
+ }
21345
+ });
21346
+ if (store && scope) await publishSubconsciousActivity({
21347
+ store,
21348
+ scope,
21349
+ recentUpdates: subconscious.activity === false ? 10 : subconscious.activity.recentUpdates,
21350
+ sendStateSignal: context.sendStateSignal,
21351
+ errors: [message]
21352
+ });
21353
+ else await publishSubconsciousError({
21354
+ error: message,
21355
+ sendStateSignal: context.sendStateSignal
21356
+ });
21357
+ throw error;
21358
+ }
21359
+ };
21360
+ }
21361
+ async function createCuratorAgent(memory, curatorMemory, context, scope, config, subconscious, omModel) {
21362
+ const model = await resolveSubconsciousAgentModel({
21363
+ config,
21364
+ omModel,
21365
+ mainAgent: context.mainAgent,
21366
+ requestContext: context.requestContext
21367
+ });
21368
+ if (!model) throw new Error("Subconscious curate requires the main agent to resolve its model.");
21369
+ return new Agent({
21370
+ id: `subconscious-curate-${context.parentThreadId}`,
21371
+ name: "Subconscious Curate",
21372
+ instructions: [
21373
+ DEFAULT_INSTRUCTIONS$1,
21374
+ subconscious.pins ? PINNED_INSTRUCTIONS : void 0,
21375
+ config.instructions?.trim()
21376
+ ].filter(Boolean).join("\n\n"),
21377
+ model,
21378
+ memory: curatorMemory,
21379
+ tools: {
21380
+ ...createKnowledgeTools(memory),
21381
+ ...createKnowledgeWriteTools(memory, {
21382
+ scope,
21383
+ sourceThreadId: context.parentThreadId,
21384
+ defaultScope: subconscious.defaultScope,
21385
+ maxScope: subconscious.maxScope
21386
+ }),
21387
+ ...subconscious.pins ? createPinnedTools(memory, {
21388
+ scope,
21389
+ sourceThreadId: context.parentThreadId,
21390
+ defaultScope: subconscious.defaultScope,
21391
+ maxScope: subconscious.maxScope,
21392
+ maxPins: subconscious.pins.maxPins,
21393
+ maxCharacters: subconscious.pins.maxCharacters
21394
+ }) : {}
21395
+ }
21396
+ });
21397
+ }
21398
+ const LEARN_AGENT = "learn";
21399
+ const ULID_ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
21400
+ const DEFAULT_INSTRUCTIONS = `Learn reusable skills from the full pre-reflection observations and pending knowledge records.
21401
+
21402
+ A skill is a repeatable procedure with ordered actions, a trigger or context, and a success or recovery outcome. Do not learn one-off events, isolated preferences, knowledge records, or procedures supported by fewer than two distinct pending knowledge records. Search existing kind:skill nodes by exact name before writing so updates extend one skill rather than creating duplicates.
21403
+
21404
+ Use knowledge_record_skill for every skill creation or evidence update. It validates the evidence frontier and writes retry-safe evidence. You may use the other scoped knowledge tools for research and maintenance, but never restore deleted records, invent provenance or versions, or write outside the source scope.
21405
+
21406
+ Process pending records in ID order. End with <learning-complete through="RECORD_ID" /> naming the last pending record you reviewed, even when no reusable skill was found. Acknowledge only records you fully reviewed.`;
21407
+ function resolveScope(context) {
21408
+ const organizationId = context.requestContext?.get("organizationId");
21409
+ if (typeof organizationId !== "string" || !organizationId.trim()) throw new Error("Subconscious learn requires organizationId in the request context.");
21410
+ return canonicalizeKnowledgeScope([
21411
+ `org:${organizationId}`,
21412
+ `resource:${resolveKnowledgeResourceId(context.requestContext, context.resourceId)}`,
21413
+ `thread:${context.parentThreadId}`
21414
+ ]);
21415
+ }
21416
+ async function readWorklist(store, sourceThreadId, scope, after) {
21417
+ const records = [];
21418
+ let cursor = after;
21419
+ do {
21420
+ const page = await store.knowledgeBySource({
21421
+ sourceThreadId,
21422
+ scope,
21423
+ after: cursor,
21424
+ limit: 100
21425
+ });
21426
+ records.push(...page.records);
21427
+ cursor = page.nextCursor;
21428
+ } while (cursor && records.length < 500);
21429
+ return {
21430
+ records,
21431
+ hasMore: Boolean(cursor)
21432
+ };
21433
+ }
21434
+ function evidenceRecordId(sourceRecordId, skillName) {
21435
+ const hash = createHash("sha256").update(`${skillName.trim().toLocaleLowerCase()}\0${sourceRecordId}`).digest();
21436
+ let suffix = "";
21437
+ for (let index = 0; index < 16; index++) suffix += ULID_ALPHABET[hash[index] & 31];
21438
+ return `${sourceRecordId.slice(0, 10)}${suffix}`;
21439
+ }
21440
+ function createLearnerRecordSkillTool(input) {
21441
+ return createTool({
21442
+ id: "knowledge_record_skill",
21443
+ description: "Create or update one reusable skill using at least two distinct pending knowledge records. Evidence writes are idempotent across retries.",
21444
+ inputSchema: {
21445
+ type: "object",
21446
+ properties: {
21447
+ name: {
21448
+ type: "string",
21449
+ minLength: 1
21450
+ },
21451
+ procedure: {
21452
+ type: "string",
21453
+ minLength: 1
21454
+ },
21455
+ sourceRecordIds: {
21456
+ type: "array",
21457
+ items: {
21458
+ type: "string",
21459
+ minLength: 1
21460
+ },
21461
+ minItems: 2,
21462
+ uniqueItems: true
21463
+ }
21464
+ },
21465
+ required: [
21466
+ "name",
21467
+ "procedure",
21468
+ "sourceRecordIds"
21469
+ ],
21470
+ additionalProperties: false
21471
+ },
21472
+ execute: async (raw) => {
21473
+ const value = raw;
21474
+ const sourceIds = [...new Set(value.sourceRecordIds)];
21475
+ const pending = new Map(input.pendingRecords.map((record) => [record.id, record]));
21476
+ if (sourceIds.length < 2 || sourceIds.some((id) => !pending.has(id))) throw new Error("Skill evidence requires at least two distinct records from the pending learner worklist.");
21477
+ const normalizedName = value.name.trim();
21478
+ if (input.state.recordedName && input.state.recordedName.toLocaleLowerCase() !== normalizedName.toLocaleLowerCase()) throw new Error("The learner may record at most one skill per reflection.");
21479
+ input.state.recordedName = normalizedName;
21480
+ const nodeScope = expandKnowledgeScope(input.scope, input.defaultScope);
21481
+ let node = await input.store.resolveNode({
21482
+ name: normalizedName,
21483
+ scope: input.scope
21484
+ });
21485
+ if (node && node.kind !== "skill") throw new Error(`Knowledge node is not a skill: ${normalizedName}`);
21486
+ node ??= await input.store.createNode({
21487
+ name: normalizedName,
21488
+ kind: "skill",
21489
+ scope: nodeScope
21490
+ });
21491
+ const evidence = [];
21492
+ for (const sourceId of sourceIds) {
21493
+ const id = evidenceRecordId(sourceId, normalizedName);
21494
+ const existing = await input.store.getKnowledge({ id });
21495
+ if (existing) {
21496
+ evidence.push(existing);
21497
+ continue;
21498
+ }
21499
+ const source = pending.get(sourceId);
21500
+ try {
21501
+ evidence.push(await input.store.appendKnowledge({
21502
+ id,
21503
+ node: node.id,
21504
+ text: `Procedure: ${value.procedure.trim()} Evidence source: ${source.id}.`,
21505
+ scope: source.scope,
21506
+ sourceThreadId: `subconscious:${input.parentThreadId}:learn`,
21507
+ maxScope: source.maxScope ?? input.maxScope,
21508
+ resolutionScope: input.scope,
21509
+ defaultScope: nodeScope
21510
+ }));
21511
+ } catch (error) {
21512
+ const raced = await input.store.getKnowledge({ id });
21513
+ if (!raced) throw error;
21514
+ evidence.push(raced);
21515
+ }
21516
+ }
21517
+ return {
21518
+ node,
21519
+ evidence
21520
+ };
21521
+ }
21522
+ });
21523
+ }
21524
+ function composeReflectionAgentHandlers(handlers) {
21525
+ return async (context) => {
21526
+ for (const handler of handlers) try {
21527
+ await handler(context);
21528
+ } catch (error) {
21529
+ if (context.abortSignal?.aborted) throw error;
21530
+ }
21531
+ };
21532
+ }
21533
+ function createLearnerHandler(memory, subconscious, learnerMemory = memory, options) {
21534
+ const config = subconscious.reflection.find((agent) => agent.name === LEARN_AGENT);
21535
+ if (!config) return async () => {};
21536
+ return async (context) => {
21537
+ let store;
21538
+ let scope;
21539
+ try {
21540
+ scope = resolveScope(context);
21541
+ store = await memory.storage.getStore("knowledge");
21542
+ if (!store) throw new Error("Subconscious learn requires a configured knowledge storage domain.");
21543
+ const cursor = await store.getCurationCursor({
21544
+ sourceThreadId: context.parentThreadId,
21545
+ agent: LEARN_AGENT
21546
+ });
21547
+ const worklist = await readWorklist(store, context.parentThreadId, scope, cursor?.lastKnowledgeId);
21548
+ if (!worklist.records.length) return;
21549
+ const acknowledgedId = (await (await createLearnerAgent(memory, learnerMemory, context, scope, worklist.records, config, subconscious, options?.omModel)).generate(`Parent thread: ${context.parentThreadId}\nCurrent time: ${(/* @__PURE__ */ new Date()).toISOString()}\nWorklist truncated: ${worklist.hasMore}\n\nFull pre-reflection observations:\n${context.observations}\n\nPending knowledge records:\n${JSON.stringify(worklist.records)}`, {
21550
+ requestContext: context.requestContext,
21551
+ abortSignal: context.abortSignal,
21552
+ maxSteps: config.maxSteps,
21553
+ memory: {
21554
+ thread: `subconscious:${context.parentThreadId}:learn`,
21555
+ resource: context.resourceId
21556
+ }
21557
+ })).text.match(/<learning-complete\s+through=["']([^"']+)["']\s*\/>/i)?.[1];
21558
+ if (!acknowledgedId || !worklist.records.some((record) => record.id === acknowledgedId)) throw new Error("Learner did not acknowledge a valid reviewed record cursor.");
21559
+ await store.advanceCurationCursor({
21560
+ sourceThreadId: context.parentThreadId,
21561
+ agent: LEARN_AGENT,
21562
+ lastKnowledgeId: acknowledgedId
21563
+ });
21564
+ } catch (error) {
21565
+ const message = `learn: ${error instanceof Error ? error.message : String(error)}`;
21566
+ await context.writer?.custom({
21567
+ type: "data-subconscious-error",
21568
+ data: {
21569
+ agent: "learn",
21570
+ error: message
21571
+ }
21572
+ });
21573
+ if (store && scope) await publishSubconsciousActivity({
21574
+ store,
21575
+ scope,
21576
+ recentUpdates: subconscious.activity === false ? 10 : subconscious.activity.recentUpdates,
21577
+ sendStateSignal: context.sendStateSignal,
21578
+ errors: [message]
21579
+ });
21580
+ else await publishSubconsciousError({
21581
+ error: message,
21582
+ sendStateSignal: context.sendStateSignal
21583
+ });
21584
+ throw error;
21585
+ }
21586
+ };
21587
+ }
21588
+ async function createLearnerAgent(memory, learnerMemory, context, scope, pendingRecords, config, subconscious, omModel) {
21589
+ const model = await resolveSubconsciousAgentModel({
21590
+ config,
21591
+ omModel,
21592
+ mainAgent: context.mainAgent,
21593
+ requestContext: context.requestContext
21594
+ });
21595
+ if (!model) throw new Error("Subconscious learn requires the main agent to resolve its model.");
21596
+ const store = await memory.storage.getStore("knowledge");
21597
+ if (!store) throw new Error("Subconscious learn requires a configured knowledge storage domain.");
21598
+ const state = {};
21599
+ return new Agent({
21600
+ id: `subconscious-learn-${context.parentThreadId}`,
21601
+ name: "Subconscious Learn",
21602
+ instructions: [DEFAULT_INSTRUCTIONS, config.instructions?.trim()].filter(Boolean).join("\n\n"),
21603
+ model,
21604
+ memory: learnerMemory,
21605
+ tools: {
21606
+ ...createKnowledgeTools(memory, scope),
21607
+ ...createKnowledgeWriteTools(memory, {
21608
+ scope,
21609
+ sourceThreadId: context.parentThreadId,
21610
+ defaultScope: subconscious.defaultScope,
21611
+ maxScope: subconscious.maxScope
21612
+ }),
21613
+ knowledge_record_skill: createLearnerRecordSkillTool({
21614
+ store,
21615
+ scope,
21616
+ pendingRecords,
21617
+ parentThreadId: context.parentThreadId,
21618
+ defaultScope: subconscious.defaultScope,
21619
+ maxScope: subconscious.maxScope,
21620
+ state
21621
+ })
21622
+ }
21623
+ });
21624
+ }
19243
21625
  var constants_exports = /* @__PURE__ */ __exportAll({
19244
21626
  OBSERVATIONAL_MEMORY_DEFAULTS: () => OBSERVATIONAL_MEMORY_DEFAULTS,
19245
21627
  OBSERVATION_CONTEXT_INSTRUCTIONS: () => OBSERVATION_CONTEXT_INSTRUCTIONS,
@@ -19394,232 +21776,6 @@ Observation groups with range IDs and your recall tool allows you to think back
19394
21776
  ### Additional recall guidance
19395
21777
  ${custom}`;
19396
21778
  }
19397
- const BUILT_IN_SLUGS = /* @__PURE__ */ new Set([
19398
- "current-task",
19399
- "suggested-response",
19400
- "thread-title"
19401
- ]);
19402
- const EXTRACTED_VALUES_TAG = "extracted-values";
19403
- const RESERVED_XML_TAGS = /* @__PURE__ */ new Set([
19404
- "observations",
19405
- "observation",
19406
- EXTRACTED_VALUES_TAG,
19407
- "thread",
19408
- "message",
19409
- "messages",
19410
- "conversation",
19411
- "history",
19412
- "system",
19413
- "user",
19414
- "assistant",
19415
- "tool",
19416
- ...BUILT_IN_SLUGS
19417
- ]);
19418
- const BUILT_IN_EXTRACTOR_SLUGS = [...BUILT_IN_SLUGS];
19419
- function isBuiltInExtractorSlug(slug) {
19420
- return BUILT_IN_SLUGS.has(slug);
19421
- }
19422
- function slugifyExtractorName(name) {
19423
- let normalized = "";
19424
- let previousWasSeparator = false;
19425
- for (const char of name.trim().toLowerCase()) {
19426
- const code = char.charCodeAt(0);
19427
- if (code >= 97 && code <= 122 || code >= 48 && code <= 57) {
19428
- normalized += char;
19429
- previousWasSeparator = false;
19430
- continue;
19431
- }
19432
- if (char === "'" || char === "\"" || char === "`") continue;
19433
- if (!previousWasSeparator && normalized.length > 0) {
19434
- normalized += "-";
19435
- previousWasSeparator = true;
19436
- }
19437
- }
19438
- return normalized.endsWith("-") ? normalized.slice(0, -1) : normalized;
19439
- }
19440
- function assertValidSlug(slug, name) {
19441
- if (!slug) throw new Error(`Extractor name "${name}" must produce a non-empty slug.`);
19442
- const first = slug.charCodeAt(0);
19443
- const last = slug.charCodeAt(slug.length - 1);
19444
- const startsWithLetter = first >= 97 && first <= 122;
19445
- const endsWithLetterOrNumber = last >= 97 && last <= 122 || last >= 48 && last <= 57;
19446
- const hasOnlySlugCharacters = [...slug].every((char) => {
19447
- const code = char.charCodeAt(0);
19448
- return code >= 97 && code <= 122 || code >= 48 && code <= 57 || char === "-";
19449
- });
19450
- if (!startsWithLetter || !endsWithLetterOrNumber || !hasOnlySlugCharacters) throw new Error(`Extractor name "${name}" produced invalid slug "${slug}".`);
19451
- }
19452
- var Extractor = class Extractor {
19453
- name;
19454
- slug;
19455
- instructions;
19456
- schema;
19457
- mode;
19458
- includePreviousExtraction;
19459
- metadataKeyPath;
19460
- onExtracted;
19461
- retryStructuredExtractionOnEmptyObject;
19462
- /** @internal */
19463
- internal;
19464
- instructionsConfig;
19465
- schemaConfig;
19466
- constructor(config, internal = false) {
19467
- const name = config.name.trim();
19468
- const instructions = typeof config.instructions === "string" ? config.instructions.trim() : void 0;
19469
- const slug = slugifyExtractorName(name);
19470
- if (!name) throw new Error("Extractor name is required.");
19471
- if (instructions !== void 0 && !instructions) throw new Error(`Extractor "${name}" must include instructions.`);
19472
- assertValidSlug(slug, name);
19473
- if (!internal && RESERVED_XML_TAGS.has(slug)) throw new Error(`Extractor slug "${slug}" is reserved by Observational Memory.`);
19474
- this.name = name;
19475
- this.slug = slug;
19476
- this.instructionsConfig = config.instructions;
19477
- this.schemaConfig = config.schema;
19478
- this.instructions = instructions ?? "";
19479
- this.schema = typeof config.schema === "function" ? z$2.string() : config.schema ?? z$2.string();
19480
- this.mode = internal || !config.schema ? "inline" : "structured";
19481
- this.includePreviousExtraction = config.includePreviousExtraction ?? true;
19482
- this.metadataKeyPath = config.metadataKeyPath ?? `extracted.${slug}`;
19483
- this.onExtracted = config.onExtracted;
19484
- this.retryStructuredExtractionOnEmptyObject = config.retryStructuredExtractionOnEmptyObject ?? false;
19485
- this.internal = internal;
19486
- }
19487
- async resolve(context) {
19488
- const instructions = typeof this.instructionsConfig === "function" ? (await this.instructionsConfig(context)).trim() : this.instructionsConfig.trim();
19489
- if (!instructions) throw new Error(`Extractor "${this.name}" must include instructions.`);
19490
- const schema = typeof this.schemaConfig === "function" ? await this.schemaConfig(context) : this.schemaConfig;
19491
- return new Extractor({
19492
- name: this.name,
19493
- instructions,
19494
- ...schema ? { schema } : {},
19495
- includePreviousExtraction: this.includePreviousExtraction,
19496
- metadataKeyPath: this.metadataKeyPath,
19497
- onExtracted: this.onExtracted,
19498
- retryStructuredExtractionOnEmptyObject: this.retryStructuredExtractionOnEmptyObject
19499
- }, this.internal);
19500
- }
19501
- };
19502
- async function resolveExtractors(extractors, context) {
19503
- return Promise.all(extractors.map((extractor) => extractor.resolve(context)));
19504
- }
19505
- function validateExtractorList(extractors) {
19506
- const seen = /* @__PURE__ */ new Map();
19507
- for (const extractor of extractors) {
19508
- assertValidSlug(extractor.slug, extractor.name);
19509
- if (!extractor.internal && RESERVED_XML_TAGS.has(extractor.slug)) throw new Error(`Extractor slug "${extractor.slug}" is reserved by Observational Memory.`);
19510
- const previous = seen.get(extractor.slug);
19511
- if (previous) throw new Error(`Duplicate extractor slug "${extractor.slug}" from "${previous}" and "${extractor.name}".`);
19512
- seen.set(extractor.slug, extractor.name);
19513
- }
19514
- return [...extractors];
19515
- }
19516
- function isJsonLike(value) {
19517
- return /^(?:[\[{"-]|\d|true\b|false\b|null\b)/.test(value.trim());
19518
- }
19519
- function candidateValues(raw) {
19520
- const trimmed = raw.trim();
19521
- const candidates = [];
19522
- const add = (value) => {
19523
- if (!candidates.some((candidate) => Object.is(candidate, value))) candidates.push(value);
19524
- };
19525
- if (isJsonLike(trimmed)) try {
19526
- add(JSON.parse(trimmed));
19527
- } catch {}
19528
- add(trimmed);
19529
- if (!isJsonLike(trimmed)) try {
19530
- add(JSON.parse(trimmed));
19531
- } catch {}
19532
- return candidates;
19533
- }
19534
- function parseExtractorValue(extractor, raw) {
19535
- const failures = [];
19536
- for (const candidate of candidateValues(raw)) {
19537
- const parsed = extractor.schema.safeParse(candidate);
19538
- if (parsed.success) return parsed.data;
19539
- failures.push(parsed.error.message);
19540
- }
19541
- throw new Error(`Extractor "${extractor.slug}" output did not match its schema: ${failures[0] ?? "invalid value"}`);
19542
- }
19543
- function parseExtractedValuesObject(raw) {
19544
- const trimmed = raw.trim();
19545
- if (!trimmed || trimmed.startsWith("Write only the extracted values JSON object here.")) return;
19546
- const parsed = JSON.parse(trimmed);
19547
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(`${EXTRACTED_VALUES_TAG} must contain a JSON object.`);
19548
- return parsed;
19549
- }
19550
- function parseExtractedValues(output, extractors) {
19551
- const values = {};
19552
- const failures = [];
19553
- const inlineExtractors = extractors.filter((extractor) => extractor.mode === "inline");
19554
- const regex = new RegExp(`<${EXTRACTED_VALUES_TAG}>([\\s\\S]*?)<\\/${EXTRACTED_VALUES_TAG}>`, "gi");
19555
- const matches = [...output.matchAll(regex)];
19556
- for (const match of matches) try {
19557
- const extractedValues = parseExtractedValuesObject(match[1] ?? "");
19558
- if (!extractedValues) continue;
19559
- for (const extractor of inlineExtractors) {
19560
- if (!Object.prototype.hasOwnProperty.call(extractedValues, extractor.slug)) continue;
19561
- const rawValue = extractedValues[extractor.slug];
19562
- if (rawValue === void 0 || rawValue === null || rawValue === "") continue;
19563
- const parsed = extractor.schema.safeParse(rawValue);
19564
- if (parsed.success) values[extractor.slug] = parsed.data;
19565
- else failures.push({
19566
- slug: extractor.slug,
19567
- error: parsed.error.message
19568
- });
19569
- }
19570
- } catch (error) {
19571
- failures.push({
19572
- slug: EXTRACTED_VALUES_TAG,
19573
- error: error instanceof Error ? error.message : String(error)
19574
- });
19575
- }
19576
- for (const extractor of inlineExtractors) {
19577
- if (Object.prototype.hasOwnProperty.call(values, extractor.slug)) continue;
19578
- const tagRegex = new RegExp(`<${extractor.slug}>([\\s\\S]*?)<\\/${extractor.slug}>`, "gi");
19579
- const rawValue = [...output.matchAll(tagRegex)].at(-1)?.[1]?.trim();
19580
- if (!rawValue) continue;
19581
- try {
19582
- values[extractor.slug] = parseExtractorValue(extractor, rawValue);
19583
- } catch (error) {
19584
- failures.push({
19585
- slug: extractor.slug,
19586
- error: error instanceof Error ? error.message : String(error)
19587
- });
19588
- }
19589
- }
19590
- return {
19591
- values,
19592
- failures
19593
- };
19594
- }
19595
- function stripExtractorSections(output, extractors) {
19596
- const inlineExtractors = extractors.filter((extractor) => extractor.mode === "inline");
19597
- let stripped = output.replace(new RegExp(`[ \\t]*<${EXTRACTED_VALUES_TAG}>[\\s\\S]*?<\\/${EXTRACTED_VALUES_TAG}>\\s*`, "gi"), "");
19598
- for (const extractor of inlineExtractors) stripped = stripped.replace(new RegExp(`[ \\t]*<${extractor.slug}>[\\s\\S]*?<\\/${extractor.slug}>\\s*`, "gi"), "");
19599
- return stripped;
19600
- }
19601
- function buildExtractorOutputSections(extractors) {
19602
- const inlineExtractors = extractors.filter((extractor) => extractor.mode === "inline");
19603
- if (inlineExtractors.length === 0) return "";
19604
- return `Additional optional XML sections:\nIf the observations include information relevant to any of these tags, output that tag after <observations> and include the relevant information.\n${inlineExtractors.map((extractor) => `<${extractor.slug}>
19605
- ${extractor.instructions}
19606
- Include this section when the observations contain relevant information for <${extractor.slug}>. Write only that information inside the tag.
19607
- </${extractor.slug}>`).join("\n\n")}`;
19608
- }
19609
- function renderPriorValue(value) {
19610
- return typeof value === "string" ? value : JSON.stringify(value);
19611
- }
19612
- function buildExtractorPriorLines(extractors, priorExtractedValues) {
19613
- if (!priorExtractedValues) return [];
19614
- const lines = [];
19615
- for (const extractor of extractors) {
19616
- if (!extractor.includePreviousExtraction) continue;
19617
- const value = priorExtractedValues[extractor.slug];
19618
- if (value === void 0 || value === null || value === "") continue;
19619
- lines.push(`<${extractor.slug}>\n${renderPriorValue(value)}\n</${extractor.slug}>`);
19620
- }
19621
- return lines;
19622
- }
19623
21779
  const BUILT_IN_METADATA_FIELDS = {
19624
21780
  "current-task": {
19625
21781
  metadataField: "currentTask",
@@ -19741,9 +21897,11 @@ async function applyExtractorHooks(opts) {
19741
21897
  const values = normalizeExtractedValues(opts.values) ?? {};
19742
21898
  const failures = [...opts.failures ?? []];
19743
21899
  for (const extractor of opts.extractors) {
19744
- if (!Object.prototype.hasOwnProperty.call(values, extractor.slug)) continue;
19745
- const current = values[extractor.slug];
19746
- if (!isPresentExtractedValue(current)) {
21900
+ const isHook = extractor.mode === "hook";
21901
+ const hasValue = Object.prototype.hasOwnProperty.call(values, extractor.slug);
21902
+ if (!isHook && !hasValue) continue;
21903
+ const current = isHook ? opts.rawObservations : values[extractor.slug];
21904
+ if (!isHook && !isPresentExtractedValue(current)) {
19747
21905
  delete values[extractor.slug];
19748
21906
  continue;
19749
21907
  }
@@ -19754,14 +21912,19 @@ async function applyExtractorHooks(opts) {
19754
21912
  extractor,
19755
21913
  threadId: opts.threadId,
19756
21914
  resourceId: opts.resourceId,
19757
- previous: opts.previousValues?.[extractor.slug],
21915
+ previous: isHook ? void 0 : opts.previousValues?.[extractor.slug],
19758
21916
  current,
21917
+ rawObservations: opts.rawObservations,
21918
+ recentMessages: opts.recentMessages,
19759
21919
  mainAgent: opts.mainAgent,
19760
21920
  memory: opts.memory,
19761
21921
  sendSignal: opts.sendSignal,
21922
+ sendStateSignal: opts.sendStateSignal,
21923
+ writer: opts.writer,
21924
+ abortSignal: opts.abortSignal,
19762
21925
  requestContext: opts.requestContext
19763
21926
  });
19764
- if (hookValue === void 0) continue;
21927
+ if (isHook || hookValue === void 0) continue;
19765
21928
  const parsed = extractor.schema.safeParse(hookValue);
19766
21929
  if (parsed.success) values[extractor.slug] = parsed.data;
19767
21930
  else {
@@ -19772,7 +21935,8 @@ async function applyExtractorHooks(opts) {
19772
21935
  });
19773
21936
  }
19774
21937
  } catch (error) {
19775
- delete values[extractor.slug];
21938
+ if (opts.abortSignal?.aborted) throw error;
21939
+ if (!isHook) delete values[extractor.slug];
19776
21940
  failures.push({
19777
21941
  slug: extractor.slug,
19778
21942
  error: error instanceof Error ? error.message : String(error)
@@ -20821,11 +22985,11 @@ function formatObserverAttachmentPlaceholder(part, counter) {
20821
22985
  const label = resolveObserverAttachmentLabel(part);
20822
22986
  return label ? `[${attachmentType} #${attachmentId}: ${label}]` : `[${attachmentType} #${attachmentId}]`;
20823
22987
  }
20824
- function isRecord$2(value) {
22988
+ function isRecord$3(value) {
20825
22989
  return !!value && typeof value === "object";
20826
22990
  }
20827
22991
  function mapToolResultBlockToAttachment(block) {
20828
- if (!isRecord$2(block) || typeof block.type !== "string") return;
22992
+ if (!isRecord$3(block) || typeof block.type !== "string") return;
20829
22993
  const mediaType = typeof block.mediaType === "string" ? block.mediaType : void 0;
20830
22994
  const filename = typeof block.filename === "string" ? block.filename : void 0;
20831
22995
  switch (block.type) {
@@ -20886,7 +23050,7 @@ function mapToolResultBlockToAttachment(block) {
20886
23050
  }
20887
23051
  }
20888
23052
  function extractToolResultAttachments(result, counter, attachmentFilter) {
20889
- if (!isRecord$2(result) || result.type !== "content" || !Array.isArray(result.value)) return {
23053
+ if (!isRecord$3(result) || result.type !== "content" || !Array.isArray(result.value)) return {
20890
23054
  resultWithoutAttachments: result,
20891
23055
  attachments: []
20892
23056
  };
@@ -20900,7 +23064,7 @@ function extractToolResultAttachments(result, counter, attachmentFilter) {
20900
23064
  if (shouldIncludeObserverAttachment(attachment, attachmentFilter)) attachments.push(toObserverInputAttachmentPart(attachment));
20901
23065
  const placeholder = formatObserverAttachmentPlaceholder(attachment, counter);
20902
23066
  return {
20903
- type: isRecord$2(block) ? block.type : void 0,
23067
+ type: isRecord$3(block) ? block.type : void 0,
20904
23068
  placeholder
20905
23069
  };
20906
23070
  });
@@ -21356,6 +23520,52 @@ function detectDegenerateRepetition(text) {
21356
23520
  return false;
21357
23521
  }
21358
23522
  /**
23523
+ * Build a single-line diagnostic description of output flagged by
23524
+ * {@link detectDegenerateRepetition}. Used when logging or surfacing a
23525
+ * degenerate-output failure so the discarded model output can be inspected —
23526
+ * without it there is no way to tell a real repetition loop apart from a
23527
+ * detector false-positive on legitimately repetitive content.
23528
+ *
23529
+ * Reuses the detector's sampling parameters (200-char windows, ~50 samples)
23530
+ * so the reported duplicate ratio and most-repeated window match what
23531
+ * triggered the detection. Snippets are JSON-escaped so the result stays on
23532
+ * one line.
23533
+ */
23534
+ function describeDegenerateOutput(text, snippetChars = 400) {
23535
+ const windowSize = 200;
23536
+ const step = Math.max(1, Math.floor(text.length / 50));
23537
+ const seen = /* @__PURE__ */ new Map();
23538
+ let duplicateWindows = 0;
23539
+ let totalWindows = 0;
23540
+ for (let i = 0; i + windowSize <= text.length; i += step) {
23541
+ const window = text.slice(i, i + windowSize);
23542
+ totalWindows++;
23543
+ const count = (seen.get(window) ?? 0) + 1;
23544
+ seen.set(window, count);
23545
+ if (count > 1) duplicateWindows++;
23546
+ }
23547
+ let topWindow = "";
23548
+ let topCount = 0;
23549
+ for (const [window, count] of seen) if (count > topCount) {
23550
+ topCount = count;
23551
+ topWindow = window;
23552
+ }
23553
+ let longestLine = 0;
23554
+ for (const line of text.split("\n")) if (line.length > longestLine) longestLine = line.length;
23555
+ const duplicateRatio = totalWindows > 0 ? (duplicateWindows / totalWindows).toFixed(2) : "n/a";
23556
+ const parts = [
23557
+ `length=${text.length}`,
23558
+ `sampledWindows=${totalWindows}`,
23559
+ `duplicateRatio=${duplicateRatio}`,
23560
+ `longestLine=${longestLine}`,
23561
+ `topWindowCount=${topCount}`
23562
+ ];
23563
+ if (topCount > 1) parts.push(`topWindow=${JSON.stringify(topWindow)}`);
23564
+ parts.push(`head=${JSON.stringify(text.slice(0, snippetChars))}`);
23565
+ if (text.length > snippetChars * 2) parts.push(`tail=${JSON.stringify(text.slice(-snippetChars))}`);
23566
+ return parts.join(" ");
23567
+ }
23568
+ /**
21359
23569
  * Check if observations contain a Current Task section.
21360
23570
  * Supports both XML format and legacy markdown format.
21361
23571
  */
@@ -21441,17 +23651,17 @@ const TRANSIENT_MESSAGE_SUBSTRINGS = [
21441
23651
  "connection reset",
21442
23652
  "connection closed"
21443
23653
  ];
21444
- function isRecord$1(value) {
23654
+ function isRecord$2(value) {
21445
23655
  return typeof value === "object" && value !== null;
21446
23656
  }
21447
23657
  function isAbortError$5(error) {
21448
- if (!isRecord$1(error)) return false;
23658
+ if (!isRecord$2(error)) return false;
21449
23659
  if (error.name === "AbortError") return true;
21450
23660
  if (typeof error.code === "string" && error.code === "ABORT_ERR") return true;
21451
23661
  return false;
21452
23662
  }
21453
23663
  function hasTransientMessage(value) {
21454
- if (!isRecord$1(value)) return false;
23664
+ if (!isRecord$2(value)) return false;
21455
23665
  const message = typeof value.message === "string" ? value.message.toLowerCase() : "";
21456
23666
  if (message && TRANSIENT_MESSAGE_SUBSTRINGS.some((sub) => message.includes(sub))) return true;
21457
23667
  if (typeof value.code === "string" && value.code.toUpperCase().startsWith("UND_ERR_")) return true;
@@ -21462,13 +23672,13 @@ function isRetryableHttpStatus(status) {
21462
23672
  return status >= 500 && status <= 599;
21463
23673
  }
21464
23674
  function hasRetryableHttpStatus(value) {
21465
- if (!isRecord$1(value)) return false;
23675
+ if (!isRecord$2(value)) return false;
21466
23676
  if (typeof value.statusCode === "number" && isRetryableHttpStatus(value.statusCode)) return true;
21467
23677
  if (typeof value.code === "number" && isRetryableHttpStatus(value.code)) return true;
21468
23678
  return false;
21469
23679
  }
21470
23680
  function hasIsRetryableFlag(value) {
21471
- if (!isRecord$1(value)) return false;
23681
+ if (!isRecord$2(value)) return false;
21472
23682
  return value.isRetryable === true;
21473
23683
  }
21474
23684
  /**
@@ -21486,14 +23696,14 @@ function isTransientLLMError(error) {
21486
23696
  if (isAbortError$5(error)) return false;
21487
23697
  const visited = /* @__PURE__ */ new WeakSet();
21488
23698
  function visit(candidate) {
21489
- if (isRecord$1(candidate)) {
23699
+ if (isRecord$2(candidate)) {
21490
23700
  if (visited.has(candidate)) return false;
21491
23701
  visited.add(candidate);
21492
23702
  }
21493
23703
  if (hasTransientMessage(candidate)) return true;
21494
23704
  if (hasRetryableHttpStatus(candidate)) return true;
21495
23705
  if (hasIsRetryableFlag(candidate)) return true;
21496
- if (isRecord$1(candidate)) {
23706
+ if (isRecord$2(candidate)) {
21497
23707
  if (visit(candidate.cause)) return true;
21498
23708
  if (visit(candidate.error)) return true;
21499
23709
  }
@@ -21750,13 +23960,13 @@ var ObserverRunner = class {
21750
23960
  let parsed = parseObserverOutput(result.text, activeExtractors);
21751
23961
  let retriedDueToDegenerate = false;
21752
23962
  if (parsed.degenerate) {
21753
- omDebug(`[OM:callObserver] degenerate repetition detected, retrying once`);
23963
+ omDebug(`[OM:callObserver] degenerate repetition detected, retrying once. ${describeDegenerateOutput(result.text, 2e3)}`);
21754
23964
  result = await doGenerate();
21755
23965
  parsed = parseObserverOutput(result.text, activeExtractors);
21756
23966
  retriedDueToDegenerate = true;
21757
23967
  if (parsed.degenerate) {
21758
- omDebug(`[OM:callObserver] degenerate repetition on retry, failing`);
21759
- throw new Error("Observer produced degenerate output after retry");
23968
+ omDebug(`[OM:callObserver] degenerate repetition on retry, failing. ${describeDegenerateOutput(result.text, 2e3)}`);
23969
+ throw new Error(`Observer produced degenerate output after retry. ${describeDegenerateOutput(result.text)}`);
21760
23970
  }
21761
23971
  }
21762
23972
  const structuredExtraction = await extractStructuredValues({
@@ -21900,13 +24110,13 @@ var ObserverRunner = class {
21900
24110
  let parsed = parseMultiThreadObserverOutput(result.text, activeExtractors);
21901
24111
  let retriedDueToDegenerate = false;
21902
24112
  if (parsed.degenerate) {
21903
- omDebug(`[OM:callMultiThreadObserver] degenerate repetition detected, retrying once`);
24113
+ omDebug(`[OM:callMultiThreadObserver] degenerate repetition detected, retrying once. ${describeDegenerateOutput(result.text, 2e3)}`);
21904
24114
  result = await doGenerate();
21905
24115
  parsed = parseMultiThreadObserverOutput(result.text, activeExtractors);
21906
24116
  retriedDueToDegenerate = true;
21907
24117
  if (parsed.degenerate) {
21908
- omDebug(`[OM:callMultiThreadObserver] degenerate repetition on retry, failing`);
21909
- throw new Error("Multi-thread observer produced degenerate output after retry");
24118
+ omDebug(`[OM:callMultiThreadObserver] degenerate repetition on retry, failing. ${describeDegenerateOutput(result.text, 2e3)}`);
24119
+ throw new Error(`Multi-thread observer produced degenerate output after retry. ${describeDegenerateOutput(result.text)}`);
21910
24120
  }
21911
24121
  }
21912
24122
  const structuredExtractionByThread = /* @__PURE__ */ new Map();
@@ -22267,7 +24477,7 @@ async function resolveImageDimensionsAsync(part) {
22267
24477
  const url = resolveHttpAssetUrl(getObjectValue(part, "image") ?? getObjectValue(part, "data"));
22268
24478
  if (!url) return existing;
22269
24479
  try {
22270
- const probeImageSize = (await import("./probe-image-size-mXCWYNrz.js").then((m) => /* @__PURE__ */ __toESM$1(m.default, 1))).default;
24480
+ const probeImageSize = (await import("./probe-image-size-Tf8sNZhU.js").then((m) => /* @__PURE__ */ __toESM$1(m.default, 1))).default;
22271
24481
  const probed = await probeImageSize(url, {
22272
24482
  open_timeout: REMOTE_IMAGE_PROBE_TIMEOUT_MS,
22273
24483
  response_timeout: REMOTE_IMAGE_PROBE_TIMEOUT_MS,
@@ -24713,38 +26923,6 @@ function createWorkingMemoryTool(config, options = {}) {
24713
26923
  tool
24714
26924
  };
24715
26925
  }
24716
- function isTieredModelTarget(model) {
24717
- if (typeof model === "string") return true;
24718
- if (!model || typeof model !== "object") return false;
24719
- return "modelId" in model || "id" in model || "providerId" in model || "provider" in model || "doGenerate" in model && "doStream" in model;
24720
- }
24721
- function normalizeThresholds(config) {
24722
- const entries = Object.entries(config.upTo);
24723
- if (entries.length === 0) throw new Error("ModelByInputTokens requires at least one threshold in \"upTo\"");
24724
- for (const [limitStr, model] of entries) {
24725
- const limit = Number(limitStr);
24726
- if (!Number.isFinite(limit) || limit <= 0) throw new Error(`ModelByInputTokens threshold keys must be positive numbers. Got: ${limitStr}`);
24727
- if (!isTieredModelTarget(model)) throw new Error(`ModelByInputTokens requires a valid model target for threshold ${limitStr}`);
24728
- }
24729
- return entries.map(([limitStr, model]) => ({
24730
- limit: Number(limitStr),
24731
- model
24732
- })).sort((a, b) => a.limit - b.limit);
24733
- }
24734
- var ModelByInputTokens = class {
24735
- thresholds;
24736
- constructor(config) {
24737
- this.thresholds = normalizeThresholds(config);
24738
- }
24739
- resolve(inputTokens) {
24740
- for (const { limit, model } of this.thresholds) if (inputTokens <= limit) return model;
24741
- const maxLimit = this.thresholds[this.thresholds.length - 1].limit;
24742
- throw new Error(`ModelByInputTokens: input token count (${inputTokens}) exceeds the largest configured threshold (${maxLimit}). Please configure a higher threshold or use a larger model.`);
24743
- }
24744
- getThresholds() {
24745
- return this.thresholds.map((t) => t.limit);
24746
- }
24747
- };
24748
26926
  const MINUTE = 6e4;
24749
26927
  const HOUR = 60 * MINUTE;
24750
26928
  const SHORT_TTL = 5 * MINUTE;
@@ -25537,6 +27715,39 @@ function reconcileObservationGroupsFromReflection(content, sourceObservations) {
25537
27715
  if (derivedGroups.length > 0) return derivedGroups.map((group) => wrapInObservationGroup(group.content, group.range, group.id, void 0, group.kind)).join("\n\n");
25538
27716
  return wrapInObservationGroup(normalizedContent, combineObservationGroupRanges(sourceGroups), generateAnchorId(), void 0, "reflection");
25539
27717
  }
27718
+ function isRecord$1(value) {
27719
+ return !!value && typeof value === "object" && !Array.isArray(value);
27720
+ }
27721
+ function isSubconsciousSignalMessage(message) {
27722
+ if (message.role !== "signal" || !isRecord$1(message.content)) return false;
27723
+ const contentMetadata = message.content.metadata;
27724
+ if (!isRecord$1(contentMetadata) || !isRecord$1(contentMetadata.signal)) return false;
27725
+ const signal = contentMetadata.signal;
27726
+ const metadata = signal.metadata;
27727
+ const attributes = signal.attributes;
27728
+ return signal.origin === "subconscious" || isRecord$1(metadata) && metadata.origin === "subconscious" || isRecord$1(attributes) && attributes.source === "subconscious";
27729
+ }
27730
+ function isSubconsciousSignalPart(part) {
27731
+ if (!part || typeof part !== "object") return false;
27732
+ const candidate = part;
27733
+ return candidate.type === "data-signal" && (candidate.data?.metadata?.origin === "subconscious" || candidate.data?.attributes?.source === "subconscious");
27734
+ }
27735
+ function stripSubconsciousSignals(messages) {
27736
+ return messages.flatMap((message) => {
27737
+ if (isSubconsciousSignalMessage(message)) return [];
27738
+ if (typeof message.content === "string") return [message];
27739
+ const parts = message.content.parts.filter((part) => !isSubconsciousSignalPart(part));
27740
+ if (parts.length === message.content.parts.length) return [message];
27741
+ if (parts.length === 0) return [];
27742
+ return [{
27743
+ ...message,
27744
+ content: {
27745
+ ...message.content,
27746
+ parts
27747
+ }
27748
+ }];
27749
+ });
27750
+ }
25540
27751
  /**
25541
27752
  * Get the maximum value from a threshold (simple number or range).
25542
27753
  */
@@ -25690,8 +27901,9 @@ var ObservationStrategy = class ObservationStrategy {
25690
27901
  if (fresh?.lastObservedAt && record.lastObservedAt && fresh.lastObservedAt > record.lastObservedAt) return { observed: false };
25691
27902
  }
25692
27903
  const { messages, existingObservations } = await this.prepare();
27904
+ const observationMessages = stripSubconsciousSignals(messages);
25693
27905
  await this.emitStartMarkers(cycleId);
25694
- const output = await this.observe(existingObservations, messages);
27906
+ const output = await this.observe(existingObservations, observationMessages);
25695
27907
  const processed = await this.process(output, existingObservations);
25696
27908
  await this.persist(processed);
25697
27909
  await this.emitEndMarkers(cycleId, processed);
@@ -25706,6 +27918,7 @@ var ObservationStrategy = class ObservationStrategy {
25706
27918
  abortSignal,
25707
27919
  mainAgent: this.opts.agent,
25708
27920
  sendSignal: this.opts.sendSignal,
27921
+ sendStateSignal: this.opts.sendStateSignal,
25709
27922
  reflectionHooks,
25710
27923
  requestContext,
25711
27924
  observabilityContext: this.opts.observabilityContext
@@ -25991,11 +28204,16 @@ var SyncObservationStrategy = class extends ObservationStrategy {
25991
28204
  values: result.extractedValues,
25992
28205
  failures: result.extractionFailures,
25993
28206
  previousValues: this.priorExtractedValues,
28207
+ rawObservations: result.observations,
28208
+ recentMessages: formatMessagesForObserver(this.opts.messages, { maxPartLength: 500 }),
25994
28209
  threadId: this.opts.threadId,
25995
28210
  resourceId: this.opts.resourceId,
25996
28211
  mainAgent: this.opts.agent,
25997
28212
  memory: this.deps.memory,
25998
28213
  sendSignal: this.opts.sendSignal,
28214
+ sendStateSignal: this.opts.sendStateSignal,
28215
+ writer: this.opts.writer,
28216
+ abortSignal: this.opts.abortSignal,
25999
28217
  requestContext: this.opts.requestContext
26000
28218
  });
26001
28219
  const output = {
@@ -26169,11 +28387,16 @@ var AsyncBufferObservationStrategy = class extends ObservationStrategy {
26169
28387
  values: result.extractedValues,
26170
28388
  failures: result.extractionFailures,
26171
28389
  previousValues: this.priorExtractedValues,
28390
+ rawObservations: result.observations,
28391
+ recentMessages: formatMessagesForObserver(messages, { maxPartLength: 500 }),
26172
28392
  threadId: this.opts.threadId,
26173
28393
  resourceId: this.opts.resourceId,
26174
28394
  mainAgent: this.opts.agent,
26175
28395
  memory: this.deps.memory,
26176
28396
  sendSignal: this.opts.sendSignal,
28397
+ sendStateSignal: this.opts.sendStateSignal,
28398
+ writer: this.opts.writer,
28399
+ abortSignal: this.opts.abortSignal,
26177
28400
  requestContext: this.opts.requestContext
26178
28401
  });
26179
28402
  return {
@@ -26506,11 +28729,25 @@ var ResourceScopedObservationStrategy = class extends ObservationStrategy {
26506
28729
  values: result.extractedValues,
26507
28730
  failures: result.extractionFailures,
26508
28731
  previousValues,
28732
+ rawObservations: result.observations,
28733
+ recentMessages: formatMessagesForObserver(threadMessages, { maxPartLength: 500 }),
26509
28734
  threadId,
26510
28735
  resourceId: this.resourceId,
26511
28736
  mainAgent: this.opts.agent,
26512
28737
  memory: this.deps.memory,
26513
- sendSignal: this.opts.sendSignal,
28738
+ sendSignal: this.opts.agent ? async (signal) => {
28739
+ const delivery = this.opts.agent.sendSignal(signal, {
28740
+ resourceId: this.resourceId,
28741
+ threadId,
28742
+ ifActive: { behavior: "deliver" },
28743
+ ifIdle: { behavior: "persist" }
28744
+ });
28745
+ await delivery.accepted;
28746
+ return delivery.signal;
28747
+ } : void 0,
28748
+ sendStateSignal: this.opts.sendStateSignal,
28749
+ writer: this.opts.writer,
28750
+ abortSignal: this.opts.abortSignal,
26514
28751
  requestContext: this.opts.requestContext
26515
28752
  });
26516
28753
  this.observationResults.push({
@@ -26823,18 +29060,21 @@ var ObservationStep = class {
26823
29060
  messageList.removeByIds(candidates.map((msg) => msg.id));
26824
29061
  for (const msg of candidates) messageList.add(msg, "memory");
26825
29062
  }
26826
- om.buffer({
29063
+ om.trackBackgroundWork(om.buffer({
26827
29064
  threadId,
26828
29065
  resourceId,
26829
29066
  messages: unobservedMessages,
26830
29067
  pendingTokens: statusSnapshot.pendingTokens,
26831
29068
  record: statusSnapshot.record,
26832
29069
  writer: this.turn.writer,
29070
+ agent: this.turn.agent,
29071
+ sendSignal: this.turn.sendSignal,
29072
+ sendStateSignal: this.turn.sendStateSignal,
26833
29073
  requestContext: this.turn.requestContext,
26834
29074
  observabilityContext: this.turn.observabilityContext
26835
29075
  }).catch((err) => {
26836
29076
  omDebug(`[OM:buffer] fire-and-forget buffer failed: ${err?.message}`);
26837
- });
29077
+ }));
26838
29078
  buffered = true;
26839
29079
  }
26840
29080
  const willObserveNow = statusSnapshot.shouldObserve && !hasIncompleteToolCalls;
@@ -27006,6 +29246,9 @@ var ObservationStep = class {
27006
29246
  messages: observableMessages,
27007
29247
  messageList,
27008
29248
  trigger: "turn-sync",
29249
+ agent: this.turn.agent,
29250
+ sendSignal: this.turn.sendSignal,
29251
+ sendStateSignal: this.turn.sendStateSignal,
27009
29252
  requestContext: this.turn.requestContext,
27010
29253
  writer: this.turn.writer,
27011
29254
  observabilityContext: this.turn.observabilityContext
@@ -27083,6 +29326,8 @@ var ObservationTurn = class {
27083
29326
  agent;
27084
29327
  /** Optional signal sender for processor-originated notifications. */
27085
29328
  sendSignal;
29329
+ /** Optional state signal sender for processor-originated snapshots. */
29330
+ sendStateSignal;
27086
29331
  /** Current actor model for this step. Updated by the processor before prepare(). */
27087
29332
  actorModelContext;
27088
29333
  /** The active assistant response message ID for this step. Updated by the processor before prepare(). */
@@ -27096,6 +29341,7 @@ var ObservationTurn = class {
27096
29341
  this.messageList = opts.messageList;
27097
29342
  this.agent = opts.agent;
27098
29343
  this.sendSignal = opts.sendSignal;
29344
+ this.sendStateSignal = opts.sendStateSignal;
27099
29345
  this.requestContext = opts.requestContext;
27100
29346
  this.observabilityContext = opts.observabilityContext;
27101
29347
  this.hooks = opts.hooks ?? {};
@@ -27200,7 +29446,7 @@ var ObservationTurn = class {
27200
29446
  const allMessages = getObservableMessages(this.messageList);
27201
29447
  const record = this._record;
27202
29448
  const unobservedMessages = this.om.getUnobservedMessages(allMessages, record);
27203
- if (unobservedMessages.length > 0) this.om.buffer({
29449
+ if (unobservedMessages.length > 0) this.om.trackBackgroundWork(this.om.buffer({
27204
29450
  threadId: this.threadId,
27205
29451
  resourceId: this.resourceId,
27206
29452
  messages: unobservedMessages,
@@ -27208,13 +29454,14 @@ var ObservationTurn = class {
27208
29454
  writer: this.writer,
27209
29455
  agent: this.agent,
27210
29456
  sendSignal: this.sendSignal,
29457
+ sendStateSignal: this.sendStateSignal,
27211
29458
  requestContext: this.requestContext,
27212
29459
  currentModel: this.actorModelContext,
27213
29460
  observabilityContext: this.observabilityContext,
27214
29461
  skipMinimumTokenCheck: true
27215
29462
  }).catch((err) => {
27216
29463
  omDebug(`[OM:turn.end] idle buffer failed: ${err?.message}`);
27217
- });
29464
+ }));
27218
29465
  }
27219
29466
  return { record: this._record };
27220
29467
  }
@@ -27612,6 +29859,7 @@ var ReflectorRunner = class {
27612
29859
  persistMarkerToMessage;
27613
29860
  getCompressionStartLevel;
27614
29861
  memory;
29862
+ onReflectionCommitted;
27615
29863
  mastra;
27616
29864
  constructor(opts) {
27617
29865
  this.reflectionConfig = opts.reflectionConfig;
@@ -27627,6 +29875,7 @@ var ReflectorRunner = class {
27627
29875
  this.getCompressionStartLevel = opts.getCompressionStartLevel;
27628
29876
  this.mastra = opts.mastra;
27629
29877
  this.memory = opts.memory;
29878
+ this.onReflectionCommitted = opts.onReflectionCommitted;
27630
29879
  }
27631
29880
  __registerMastra(mastra) {
27632
29881
  this.mastra = mastra;
@@ -27694,6 +29943,8 @@ var ReflectorRunner = class {
27694
29943
  };
27695
29944
  let reflectedTokens = 0;
27696
29945
  let attemptNumber = 0;
29946
+ /** Observations from the previous attempt, used to detect a no-progress ladder. */
29947
+ let previousObservations;
27697
29948
  while (currentLevel <= maxLevel) {
27698
29949
  attemptNumber++;
27699
29950
  const isRetry = attemptNumber > 1;
@@ -27758,7 +30009,7 @@ var ReflectorRunner = class {
27758
30009
  finalProviderMetadata = result.providerMetadata ?? finalProviderMetadata;
27759
30010
  parsed = parseReflectorOutput(result.text, observations, activeExtractors);
27760
30011
  if (parsed.degenerate) {
27761
- omDebug(`[OM:callReflector] attempt #${attemptNumber}: degenerate repetition detected, treating as compression failure`);
30012
+ omDebug(`[OM:callReflector] attempt #${attemptNumber}: degenerate repetition detected, treating as compression failure. ${describeDegenerateOutput(result.text, 2e3)}`);
27762
30013
  reflectedTokens = originalTokens;
27763
30014
  } else reflectedTokens = this.tokenCounter.countObservations(parsed.observations);
27764
30015
  omDebug(`[OM:callReflector] attempt #${attemptNumber} parsed: reflectedTokens=${reflectedTokens}, targetThreshold=${targetThreshold}, compressionValid=${validateCompression(reflectedTokens, targetThreshold)}, parsedObsLen=${parsed.observations?.length}, degenerate=${parsed.degenerate ?? false}`);
@@ -27767,6 +30018,11 @@ var ReflectorRunner = class {
27767
30018
  omDebug(`[OM:callReflector] degenerate output persists at maxLevel=${maxLevel}, breaking`);
27768
30019
  break;
27769
30020
  }
30021
+ if (!parsed.degenerate && previousObservations !== void 0 && parsed.observations === previousObservations) {
30022
+ omDebug(`[OM:callReflector] attempt #${attemptNumber} returned output identical to the previous attempt; escalating cannot help, stopping the ladder`);
30023
+ break;
30024
+ }
30025
+ previousObservations = parsed.observations;
27770
30026
  if (streamContext?.writer) {
27771
30027
  const failedMarker = createObservationFailedMarker({
27772
30028
  cycleId: streamContext.cycleId,
@@ -27823,6 +30079,8 @@ var ReflectorRunner = class {
27823
30079
  mainAgent,
27824
30080
  memory: this.memory,
27825
30081
  sendSignal,
30082
+ writer: streamContext?.writer,
30083
+ abortSignal,
27826
30084
  requestContext
27827
30085
  });
27828
30086
  const extractedValues = hookedValues.values;
@@ -27978,7 +30236,7 @@ var ReflectorRunner = class {
27978
30236
  * "activated", "no buffer present", and "suppressed by overshoot guard"
27979
30237
  * without re-deriving that state.
27980
30238
  */
27981
- async tryActivateBufferedReflection(record, lockKey, writer, messageList, activationMetadata) {
30239
+ async tryActivateBufferedReflection(record, lockKey, writer, messageList, activationMetadata, committedContext) {
27982
30240
  const bufferKey = this.buffering.getReflectionBufferKey(lockKey);
27983
30241
  const asyncOp = BufferingCoordinator.asyncBufferingOps.get(bufferKey);
27984
30242
  if (asyncOp) if (activationMetadata?.triggeredBy === "ttl" || activationMetadata?.triggeredBy === "provider_change") omDebug(`[OM:reflect] tryActivateBufferedReflection: async op in progress, not blocking for ${activationMetadata.triggeredBy} trigger`);
@@ -27997,7 +30255,8 @@ var ReflectorRunner = class {
27997
30255
  }
27998
30256
  const beforeTokens = freshRecord.observationTokenCount ?? 0;
27999
30257
  const reflectedLineCount = freshRecord.reflectedObservationLineCount ?? 0;
28000
- const unreflectedLines = (freshRecord.activeObservations ?? "").split("\n").slice(reflectedLineCount);
30258
+ const allLines = (freshRecord.activeObservations ?? "").split("\n");
30259
+ const unreflectedLines = allLines.slice(reflectedLineCount);
28001
30260
  const unreflectedContent = unreflectedLines.join("\n").trim();
28002
30261
  const combinedObservations = unreflectedContent ? `${freshRecord.bufferedReflection}\n\n${unreflectedContent}` : freshRecord.bufferedReflection;
28003
30262
  const combinedTokenCount = this.tokenCounter.countObservations(combinedObservations);
@@ -28028,6 +30287,11 @@ var ReflectorRunner = class {
28028
30287
  currentRecord: freshRecord,
28029
30288
  tokenCount: combinedTokenCount
28030
30289
  });
30290
+ if (committedContext) await this.notifyReflectionCommitted({
30291
+ ...committedContext,
30292
+ observations: allLines.slice(0, reflectedLineCount).join("\n").trim(),
30293
+ writer
30294
+ });
28031
30295
  BufferingCoordinator.lastBufferedBoundary.delete(bufferKey);
28032
30296
  const afterRecord = await this.storage.getObservationalMemory(record.threadId, record.resourceId);
28033
30297
  const afterTokens = afterRecord?.observationTokenCount ?? 0;
@@ -28063,13 +30327,21 @@ var ReflectorRunner = class {
28063
30327
  BufferingCoordinator.reflectionBufferCycleIds.delete(bufferKey);
28064
30328
  return { status: "activated" };
28065
30329
  }
30330
+ async notifyReflectionCommitted(context) {
30331
+ if (!this.onReflectionCommitted || !context.parentThreadId || !context.resourceId) return;
30332
+ try {
30333
+ await this.onReflectionCommitted(context);
30334
+ } catch (error) {
30335
+ omDebug(`[OM:reflect] post-commit reflection agent failed: ${error}`);
30336
+ }
30337
+ }
28066
30338
  /**
28067
30339
  * Check if reflection needed and trigger if so.
28068
30340
  * Supports both synchronous reflection and async buffered reflection.
28069
30341
  * @internal Used by observation strategies. Do not call directly.
28070
30342
  */
28071
30343
  async maybeReflect(opts) {
28072
- const { record, observationTokens, writer, abortSignal, mainAgent, sendSignal, messageList, currentModel, reflectionHooks, requestContext, observabilityContext, lastActivityAt, threadId: requestedThreadId } = opts;
30344
+ const { record, observationTokens, writer, abortSignal, mainAgent, sendSignal, sendStateSignal, messageList, currentModel, reflectionHooks, requestContext, observabilityContext, lastActivityAt, threadId: requestedThreadId } = opts;
28073
30345
  const lockKey = this.buffering.getLockKey(record.threadId, record.resourceId);
28074
30346
  const reflectThreshold = getMaxThreshold(this.getEffectiveReflectionTokens(record));
28075
30347
  const priorExtractedValues = await getThreadExtractedValues(this.storage, this.reflectionConfig.extractors, requestedThreadId ?? record.threadId);
@@ -28114,7 +30386,15 @@ var ReflectorRunner = class {
28114
30386
  await this.storage.setReflectingFlag(record.id, false);
28115
30387
  }
28116
30388
  if (this.buffering.isAsyncReflectionEnabled()) {
28117
- const activationResult = await this.tryActivateBufferedReflection(record, lockKey, writer, messageList, activationMetadata);
30389
+ const activationResult = await this.tryActivateBufferedReflection(record, lockKey, writer, messageList, activationMetadata, {
30390
+ parentThreadId: requestedThreadId ?? record.threadId ?? "",
30391
+ resourceId: record.resourceId ?? "",
30392
+ requestContext,
30393
+ mainAgent,
30394
+ sendStateSignal,
30395
+ abortSignal,
30396
+ observabilityContext
30397
+ });
28118
30398
  if (activationResult.status === "activated") return;
28119
30399
  if (activationResult.status === "suppressed") {
28120
30400
  omDebug(`[OM:reflect] skipping sync fallback / re-buffer after suppressed early ${activationMetadata.triggeredBy} activation (reason=${activationResult.reason})`);
@@ -28185,6 +30465,17 @@ var ReflectorRunner = class {
28185
30465
  reflection: reflectResult.observations,
28186
30466
  tokenCount: reflectionTokenCount
28187
30467
  });
30468
+ await this.notifyReflectionCommitted({
30469
+ parentThreadId: requestedThreadId ?? record.threadId ?? "",
30470
+ resourceId: record.resourceId ?? "",
30471
+ observations: record.activeObservations ?? "",
30472
+ requestContext,
30473
+ mainAgent,
30474
+ sendStateSignal,
30475
+ writer,
30476
+ abortSignal,
30477
+ observabilityContext
30478
+ });
28188
30479
  if (writer && streamContext) {
28189
30480
  const endMarker = createObservationEndMarker({
28190
30481
  cycleId: streamContext.cycleId,
@@ -28710,6 +31001,7 @@ var ObservationalMemory = class ObservationalMemory {
28710
31001
  hasher = e();
28711
31002
  mastra;
28712
31003
  memory;
31004
+ curationCadence;
28713
31005
  /**
28714
31006
  * Track message IDs observed during this instance's lifetime.
28715
31007
  * Prevents re-observing messages when per-thread lastObservedAt cursors
@@ -28741,6 +31033,39 @@ var ObservationalMemory = class ObservationalMemory {
28741
31033
  */
28742
31034
  recordInitializations = /* @__PURE__ */ new Map();
28743
31035
  /**
31036
+ * In-flight fire-and-forget background cycles (buffered observation, reflection).
31037
+ * Tracked so callers can join them via `settled()` before closing a storage
31038
+ * connection they own — otherwise a background cycle's tail statements race the close.
31039
+ */
31040
+ pendingBackgroundWork = /* @__PURE__ */ new Set();
31041
+ /**
31042
+ * Register fire-and-forget background work so `settled()` can join it.
31043
+ * Returns the original promise so callers keep their own rejection handling.
31044
+ */
31045
+ trackBackgroundWork(work) {
31046
+ const tracked = work.catch(() => {}).finally(() => {
31047
+ this.pendingBackgroundWork.delete(tracked);
31048
+ });
31049
+ this.pendingBackgroundWork.add(tracked);
31050
+ return work;
31051
+ }
31052
+ /**
31053
+ * Resolve once all background observational-memory work started so far has finished.
31054
+ *
31055
+ * Background cycles enqueue further background work (a buffered observation can
31056
+ * trigger a reflection, which runs nested agent streams), so this drains repeatedly
31057
+ * until nothing is left rather than joining a single snapshot.
31058
+ */
31059
+ async settled() {
31060
+ const maxDrainRounds = 100;
31061
+ for (let round = 0; round < maxDrainRounds; round++) {
31062
+ if (this.pendingBackgroundWork.size === 0) return;
31063
+ await Promise.allSettled([...this.pendingBackgroundWork]);
31064
+ }
31065
+ if (this.pendingBackgroundWork.size === 0) return;
31066
+ omError(`[OM:settled] background work still pending after ${maxDrainRounds} drain rounds; giving up waiting`);
31067
+ }
31068
+ /**
28744
31069
  * Acquire a lock for the given key, execute the callback, then release.
28745
31070
  * If a lock is already held, waits for it to be released before acquiring.
28746
31071
  */
@@ -28774,6 +31099,7 @@ var ObservationalMemory = class ObservationalMemory {
28774
31099
  this.hooks = config.hooks;
28775
31100
  this.mastra = config.mastra;
28776
31101
  this.memory = config.memory;
31102
+ this.curationCadence = config.curationCadence;
28777
31103
  const resolveModel = (model, defaultModel) => model === "default" ? defaultModel : model;
28778
31104
  const observationModel = resolveModel(config.model, OBSERVATIONAL_MEMORY_DEFAULTS.observation.model) ?? resolveModel(config.observation?.model, OBSERVATIONAL_MEMORY_DEFAULTS.observation.model) ?? resolveModel(config.reflection?.model, OBSERVATIONAL_MEMORY_DEFAULTS.observation.model) ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.model;
28779
31105
  const reflectionModel = resolveModel(config.model, OBSERVATIONAL_MEMORY_DEFAULTS.reflection.model) ?? resolveModel(config.reflection?.model, OBSERVATIONAL_MEMORY_DEFAULTS.reflection.model) ?? resolveModel(config.observation?.model, OBSERVATIONAL_MEMORY_DEFAULTS.reflection.model) ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.model;
@@ -28869,7 +31195,8 @@ var ObservationalMemory = class ObservationalMemory {
28869
31195
  getCompressionStartLevel: (rc) => this.getCompressionStartLevel(rc),
28870
31196
  resolveModel: (inputTokens) => this.resolveReflectionModel(inputTokens),
28871
31197
  mastra: config.mastra,
28872
- memory: this.memory
31198
+ memory: this.memory,
31199
+ onReflectionCommitted: config.onReflectionCommitted
28873
31200
  });
28874
31201
  this.validateBufferConfig();
28875
31202
  omDebug(`[OM:init] new ObservationalMemory instance created — scope=${this.scope}, messageTokens=${JSON.stringify(this.observationConfig.messageTokens)}, obsAsyncEnabled=${this.buffering.isAsyncObservationEnabled()}, bufferTokens=${this.observationConfig.bufferTokens}, bufferActivation=${this.observationConfig.bufferActivation}, blockAfter=${this.observationConfig.blockAfter}, reflectionTokens=${this.reflectionConfig.observationTokens}, refAsyncEnabled=${this.buffering.isAsyncReflectionEnabled()}, refAsyncActivation=${this.reflectionConfig.bufferActivation}, refBlockAfter=${this.reflectionConfig.blockAfter}`);
@@ -29741,7 +32068,7 @@ ${formattedMessages}
29741
32068
  if (!this.buffering.isAsyncObservationEnabled()) return false;
29742
32069
  const lockKey = this.buffering.getLockKey(opts.threadId, opts.resourceId);
29743
32070
  const shouldTrigger = this.buffering.shouldTriggerAsyncObservation(opts.pendingTokens, lockKey, opts.record, this.storage, opts.threshold);
29744
- if (shouldTrigger) this.startAsyncBufferedObservation(opts.record, opts.threadId, opts.unobservedMessages, lockKey, opts.writer, opts.unbufferedPendingTokens, opts.requestContext);
32071
+ if (shouldTrigger) this.trackBackgroundWork(this.startAsyncBufferedObservation(opts.record, opts.threadId, opts.unobservedMessages, lockKey, opts.writer, opts.unbufferedPendingTokens, opts.requestContext));
29745
32072
  return shouldTrigger;
29746
32073
  }
29747
32074
  isMessageList(value) {
@@ -30343,6 +32670,7 @@ ${formattedMessages}
30343
32670
  writer,
30344
32671
  agent: opts.agent,
30345
32672
  sendSignal: opts.sendSignal,
32673
+ sendStateSignal: opts.sendStateSignal,
30346
32674
  requestContext,
30347
32675
  currentModel: opts.currentModel,
30348
32676
  observabilityContext
@@ -30687,6 +33015,8 @@ ${formattedMessages}
30687
33015
  messageList: opts.messageList,
30688
33016
  reflectionHooks,
30689
33017
  agent: opts.agent,
33018
+ sendSignal: opts.sendSignal,
33019
+ sendStateSignal: opts.sendStateSignal,
30690
33020
  requestContext,
30691
33021
  writer: opts.writer,
30692
33022
  observabilityContext: opts.observabilityContext
@@ -30707,6 +33037,9 @@ ${formattedMessages}
30707
33037
  });
30708
33038
  const record = await this.getOrCreateRecord(threadId, resourceId);
30709
33039
  const reflected = record.generationCount > generationBefore && generationBefore >= 0;
33040
+ if (observed) this.maybeTriggerCadenceCuration(threadId, resourceId, record, requestContext).catch((error) => {
33041
+ omDebug(`[OM:observe] cadence curation failed: ${error instanceof Error ? error.message : String(error)}`);
33042
+ });
30710
33043
  return {
30711
33044
  observed,
30712
33045
  reflected,
@@ -30714,6 +33047,31 @@ ${formattedMessages}
30714
33047
  };
30715
33048
  }
30716
33049
  /**
33050
+ * Count committed observation runs on the sync observe path and run the curator every
33051
+ * `curationCadence` runs. The counter is persisted at `record.config.subconscious.observationRuns`
33052
+ * (the OM record's config jsonb, deep-merged; threshold resolution only reads `_overrides`, so the
33053
+ * sibling key is inert). Concurrent commits can miscount — the curator run is advisory, and the
33054
+ * curation cursor is the real serializer. The async-buffer lane bypasses observe(); deployments
33055
+ * that gate on this cadence (factory's resource scope) disable async buffering.
33056
+ */
33057
+ async maybeTriggerCadenceCuration(threadId, resourceId, record, requestContext) {
33058
+ const cadence = this.curationCadence;
33059
+ const memory = this.memory;
33060
+ if (!cadence || cadence < 1 || !memory) return;
33061
+ const runs = ((record.config ?? {}).subconscious?.observationRuns ?? 0) + 1;
33062
+ const fire = runs >= cadence;
33063
+ await this.storage.updateObservationalMemoryConfig({
33064
+ id: record.id,
33065
+ config: { subconscious: { observationRuns: fire ? 0 : runs } }
33066
+ });
33067
+ if (!fire) return;
33068
+ omDebug(`[OM:observe] cadence curation outcome=${(await memory.runCuration({
33069
+ threadId,
33070
+ resourceId: resourceId ?? threadId,
33071
+ requestContext
33072
+ })).outcome} thread=${threadId}`);
33073
+ }
33074
+ /**
30717
33075
  * Manually trigger reflection with optional guidance prompt.
30718
33076
  *
30719
33077
  * @example
@@ -30731,6 +33089,18 @@ ${formattedMessages}
30731
33089
  record,
30732
33090
  usage: void 0
30733
33091
  };
33092
+ if (record.isReflecting) {
33093
+ if (isOpActiveInProcess(record.id, "reflecting")) {
33094
+ omDebug(`[OM:reflect] isReflecting=true and active in this process, skipping`);
33095
+ return {
33096
+ reflected: false,
33097
+ record,
33098
+ usage: void 0
33099
+ };
33100
+ }
33101
+ omDebug(`[OM:reflect] isReflecting=true but NOT active in this process — stale flag from dead process, clearing`);
33102
+ await this.storage.setReflectingFlag(record.id, false);
33103
+ }
30734
33104
  await this.storage.setReflectingFlag(record.id, true);
30735
33105
  registerOp(record.id, "reflecting");
30736
33106
  const hooks = this.composeHooks(void 0, {
@@ -30916,6 +33286,8 @@ ${formattedMessages}
30916
33286
  resourceId: opts.resourceId,
30917
33287
  messageList: opts.messageList,
30918
33288
  agent: opts.agent,
33289
+ sendSignal: opts.sendSignal,
33290
+ sendStateSignal: opts.sendStateSignal,
30919
33291
  observabilityContext: opts.observabilityContext,
30920
33292
  hooks: opts.hooks
30921
33293
  });
@@ -31138,6 +33510,7 @@ var ObservationalMemoryProcessor = class {
31138
33510
  });
31139
33511
  this.turn.writer = writer;
31140
33512
  this.turn.sendSignal = args.sendSignal;
33513
+ this.turn.sendStateSignal = args.sendStateSignal;
31141
33514
  this.turn.agent = args.agent;
31142
33515
  this.turn.requestContext = requestContext;
31143
33516
  await this.turn.start(this.memory);
@@ -31278,6 +33651,7 @@ function getObservationsAsOf(activeObservations, asOf) {
31278
33651
  }
31279
33652
  var observational_memory_exports = /* @__PURE__ */ __exportAll({
31280
33653
  Extractor: () => Extractor,
33654
+ KnowledgeSemanticIndexCoordinator: () => KnowledgeSemanticIndexCoordinator,
31281
33655
  ModelByInputTokens: () => ModelByInputTokens,
31282
33656
  OBSERVATIONAL_MEMORY_DEFAULTS: () => OBSERVATIONAL_MEMORY_DEFAULTS,
31283
33657
  OBSERVATION_CONTEXT_INSTRUCTIONS: () => OBSERVATION_CONTEXT_INSTRUCTIONS,
@@ -31286,10 +33660,16 @@ var observational_memory_exports = /* @__PURE__ */ __exportAll({
31286
33660
  OBSERVER_SYSTEM_PROMPT: () => OBSERVER_SYSTEM_PROMPT,
31287
33661
  ObservationalMemory: () => ObservationalMemory,
31288
33662
  ObservationalMemoryProcessor: () => ObservationalMemoryProcessor,
33663
+ SUBCONSCIOUS_ACTIVITY_STATE_ID: () => SUBCONSCIOUS_ACTIVITY_STATE_ID,
33664
+ StaleKnowledgeSemanticIndexError: () => StaleKnowledgeSemanticIndexError,
33665
+ Subconscious: () => Subconscious,
33666
+ SubconsciousCaptureExtractor: () => SubconsciousCaptureExtractor,
33667
+ SubconsciousRemindExtractor: () => SubconsciousRemindExtractor,
31289
33668
  TokenCounter: () => TokenCounter,
31290
33669
  WorkingMemoryExtractor: () => WorkingMemoryExtractor,
31291
33670
  buildObserverPrompt: () => buildObserverPrompt,
31292
33671
  buildObserverSystemPrompt: () => buildObserverSystemPrompt,
33672
+ buildSubconsciousActivitySnapshot: () => buildSubconsciousActivitySnapshot,
31293
33673
  combineObservationGroupRanges: () => combineObservationGroupRanges,
31294
33674
  deriveObservationGroupProvenance: () => deriveObservationGroupProvenance,
31295
33675
  extractCurrentTask: () => extractCurrentTask,
@@ -31301,10 +33681,13 @@ var observational_memory_exports = /* @__PURE__ */ __exportAll({
31301
33681
  parseAnchorId: () => parseAnchorId,
31302
33682
  parseObservationGroups: () => parseObservationGroups,
31303
33683
  parseObserverOutput: () => parseObserverOutput,
33684
+ publishSubconsciousActivity: () => publishSubconsciousActivity,
31304
33685
  reconcileObservationGroupsFromReflection: () => reconcileObservationGroupsFromReflection,
31305
33686
  renderObservationGroupsForReflection: () => renderObservationGroupsForReflection,
33687
+ renderSubconsciousActivity: () => renderSubconsciousActivity,
31306
33688
  stripEphemeralAnchorIds: () => stripEphemeralAnchorIds,
31307
33689
  stripObservationGroups: () => stripObservationGroups,
33690
+ subconsciousCaptureSchema: () => subconsciousCaptureSchema,
31308
33691
  summarizeConversation: () => summarizeConversation,
31309
33692
  wrapInObservationGroup: () => wrapInObservationGroup
31310
33693
  });
@@ -31528,10 +33911,11 @@ const DEFAULT_EMBEDDING_CACHE_MAX_SIZE = 1e3;
31528
33911
  * Concrete implementation of MastraMemory that adds support for thread configuration
31529
33912
  * and message injection.
31530
33913
  */
31531
- var Memory = class extends MastraMemory {
33914
+ var Memory = class Memory extends MastraMemory {
31532
33915
  _omEngine;
31533
33916
  _omEngineInstance;
31534
33917
  _mastraInstance;
33918
+ _knowledgeSemanticIndex;
31535
33919
  /**
31536
33920
  * Every vector cleanup that deleteThread or deleteMessages started in the background.
31537
33921
  * Callers do not wait for the cleanup, so this handle is the only join point.
@@ -31544,6 +33928,25 @@ var Memory = class extends MastraMemory {
31544
33928
  trackVectorCleanup(cleanup) {
31545
33929
  this.pendingVectorCleanup = Promise.allSettled([this.pendingVectorCleanup, cleanup]).then(() => void 0);
31546
33930
  }
33931
+ /**
33932
+ * Resolve once all background work this Memory started has finished: observational-memory
33933
+ * cycles (buffered observation and reflection, including the nested agent runs they spawn)
33934
+ * and vector cleanup from `deleteThread` / `deleteMessages`.
33935
+ *
33936
+ * Callers that own the storage connection should await this before closing it, otherwise
33937
+ * background statements can race the close.
33938
+ *
33939
+ * ```ts
33940
+ * await agent.generate('hello', { memory: { thread, resource } });
33941
+ * await memory.settled();
33942
+ * await store.close();
33943
+ * ```
33944
+ */
33945
+ async settled() {
33946
+ await this.pendingVectorCleanup;
33947
+ await (this._omEngine ? await this._omEngine : this._omEngineInstance)?.settled();
33948
+ await this.pendingVectorCleanup;
33949
+ }
31547
33950
  /** The shared ObservationalMemory engine. Lazily created on first access. */
31548
33951
  get omEngine() {
31549
33952
  if (!this._omEngine) this._omEngine = this._initOMEngine().then((engine) => {
@@ -31560,7 +33963,60 @@ var Memory = class extends MastraMemory {
31560
33963
  else this._omEngine?.then((engine) => engine?.__registerMastra(mastra));
31561
33964
  }
31562
33965
  getMergedThreadConfig(config) {
31563
- return this.applyManagedWorkingMemoryDefaults(super.getMergedThreadConfig(config));
33966
+ const merged = super.getMergedThreadConfig(config);
33967
+ return this.applyManagedWorkingMemoryDefaults(this.applySubconsciousDefaults(merged));
33968
+ }
33969
+ applySubconsciousDefaults(config) {
33970
+ const omConfig = normalizeObservationalMemoryConfig(config.observationalMemory);
33971
+ if (!omConfig?.experimental_subconscious) return config;
33972
+ if (!(omConfig.experimental_subconscious instanceof Subconscious)) throw new Error("observationalMemory.experimental_subconscious must be a Subconscious instance.");
33973
+ const observation = omConfig.observation ?? {};
33974
+ const extract = observation.extract ?? [];
33975
+ const existingSlugs = new Set(extract.map((extractor) => extractor.slug));
33976
+ const subconsciousExtractors = omConfig.experimental_subconscious.createObservationExtractors(observation.model ?? omConfig.model).filter((extractor) => !existingSlugs.has(extractor.slug));
33977
+ return {
33978
+ ...config,
33979
+ observationalMemory: {
33980
+ ...omConfig,
33981
+ observation: {
33982
+ ...observation,
33983
+ extract: [...extract, ...subconsciousExtractors]
33984
+ }
33985
+ }
33986
+ };
33987
+ }
33988
+ /** Threads with a curation currently in flight in this process; guards same-process double-fire only. */
33989
+ _curationsInFlight = /* @__PURE__ */ new Set();
33990
+ /**
33991
+ * Run the subconscious curator directly over the pending fact worklist, without a reflection.
33992
+ * Cross-process serialization is the curation cursor's job; a lost race wastes one advisory run.
33993
+ *
33994
+ * Outcomes: `ran` (curator executed), `no-op` (empty worklist and no prompt, or no curate agent
33995
+ * configured), `skipped` (a curation for this thread is already in flight in this process), and
33996
+ * `no-model` (no per-agent, observational memory, or main-agent model could be resolved).
33997
+ */
33998
+ async runCuration(options) {
33999
+ const omConfig = normalizeObservationalMemoryConfig(this.threadConfig.observationalMemory);
34000
+ const subconscious = omConfig?.experimental_subconscious;
34001
+ if (!omConfig || !(subconscious instanceof Subconscious)) return { outcome: "no-op" };
34002
+ if (this._curationsInFlight.has(options.threadId)) return { outcome: "skipped" };
34003
+ this._curationsInFlight.add(options.threadId);
34004
+ try {
34005
+ return { outcome: await createCuratorHandler(this, subconscious.resolved, new Memory({
34006
+ storage: this.storage,
34007
+ options: { observationalMemory: false }
34008
+ }), { omModel: omConfig.observation?.model ?? omConfig.model })({
34009
+ parentThreadId: options.threadId,
34010
+ resourceId: options.resourceId,
34011
+ observations: options.prompt ?? "",
34012
+ requestContext: options.requestContext
34013
+ }) === "ran" ? "ran" : "no-op" };
34014
+ } catch (error) {
34015
+ if (error instanceof Error && error.message.includes("requires the main agent to resolve its model")) return { outcome: "no-model" };
34016
+ throw error;
34017
+ } finally {
34018
+ this._curationsInFlight.delete(options.threadId);
34019
+ }
31564
34020
  }
31565
34021
  applyManagedWorkingMemoryDefaults(config) {
31566
34022
  const omConfig = normalizeObservationalMemoryConfig(config.observationalMemory);
@@ -31604,6 +34060,28 @@ var Memory = class extends MastraMemory {
31604
34060
  if (!this.vector) throw new Error("`retrieval: { vector: true }` requires a vector store. Pass a `vector` option to your Memory instance.");
31605
34061
  if (!this.embedder) throw new Error("`retrieval: { vector: true }` requires an embedder. Pass an `embedder` option to your Memory instance.");
31606
34062
  }
34063
+ if (omConfig?.experimental_subconscious) {
34064
+ if (!this.vector) throw new Error("Subconscious semantic knowledge requires a vector store. Pass a `vector` option to Memory.");
34065
+ if (!this.embedder) throw new Error("Subconscious semantic knowledge requires an embedder. Pass an `embedder` option to Memory.");
34066
+ }
34067
+ }
34068
+ async getKnowledgeStore() {
34069
+ const store = await this.storage.getStore("knowledge");
34070
+ if (!store) throw new Error(`Knowledge storage domain is not available on ${this.storage.constructor.name}`);
34071
+ return store;
34072
+ }
34073
+ async getKnowledgeSemanticIndex() {
34074
+ if (!this.vector || !this.embedder) throw new Error("Subconscious semantic knowledge requires both a vector store and an embedder.");
34075
+ this._knowledgeSemanticIndex ??= this.getKnowledgeStore().then((knowledge) => new KnowledgeSemanticIndexCoordinator({
34076
+ knowledge,
34077
+ vector: this.vector,
34078
+ embedder: this.embedder,
34079
+ embedderOptions: this.embedderOptions
34080
+ }));
34081
+ return this._knowledgeSemanticIndex;
34082
+ }
34083
+ async drainKnowledgeSemanticIndex(scope) {
34084
+ return (await this.getKnowledgeSemanticIndex()).drain(scope);
31607
34085
  }
31608
34086
  /**
31609
34087
  * Gets the memory storage domain, throwing if not available.
@@ -32372,6 +34850,7 @@ ${workingMemory}`;
32372
34850
  if (!coreFeatures.has("observationalMemory")) throw new Error("Observational memory is enabled but the installed version of @mastra/core does not support it. Please upgrade @mastra/core to a version that includes observational memory support.");
32373
34851
  if (omConfig.observation?.bufferTokens !== false && !coreFeatures.has("asyncBuffering")) throw new Error("Observational memory async buffering is enabled by default but the installed version of @mastra/core does not support it. Either upgrade @mastra/core, @mastra/memory, and your storage adapter (@mastra/libsql, @mastra/pg, @mastra/mongodb, or @mastra/convex) to the latest version, or explicitly disable async buffering by setting `observation: { bufferTokens: false }` in your observationalMemory config.");
32374
34852
  if (!coreFeatures.has("request-response-id-rotation")) throw new Error("Observational memory requires @mastra/core support for request-response-id-rotation. Please bump @mastra/core to a newer version.");
34853
+ if (omConfig.experimental_subconscious) await this.getKnowledgeStore();
32375
34854
  const { ObservationalMemory: OMClass } = await Promise.resolve().then(() => observational_memory_exports);
32376
34855
  const onIndexObservations = this.hasRetrievalSearch(omConfig.retrieval) ? async (observation) => {
32377
34856
  await this.indexObservation(observation);
@@ -32385,9 +34864,21 @@ ${workingMemory}`;
32385
34864
  activateOnProviderChange: omConfig.activateOnProviderChange,
32386
34865
  shareTokenBudget: omConfig.shareTokenBudget,
32387
34866
  model: omConfig.model,
34867
+ curationCadence: omConfig.experimental_subconscious instanceof Subconscious ? omConfig.experimental_subconscious.resolved.curationCadence : void 0,
32388
34868
  mastra: this._mastraInstance,
32389
34869
  onIndexObservations,
32390
34870
  hooks: omConfig.hooks,
34871
+ onReflectionCommitted: omConfig.experimental_subconscious instanceof Subconscious ? (() => {
34872
+ const resolved = omConfig.experimental_subconscious.resolved;
34873
+ const omModel = omConfig.observation?.model ?? omConfig.model;
34874
+ return composeReflectionAgentHandlers([createCuratorHandler(this, resolved, new Memory({
34875
+ storage: this.storage,
34876
+ options: { observationalMemory: false }
34877
+ }), { omModel }), createLearnerHandler(this, resolved, new Memory({
34878
+ storage: this.storage,
34879
+ options: { observationalMemory: false }
34880
+ }), { omModel })]);
34881
+ })() : void 0,
32391
34882
  observation: omConfig.observation ? {
32392
34883
  model: omConfig.observation.model,
32393
34884
  messageTokens: omConfig.observation.messageTokens,
@@ -32777,6 +35268,7 @@ Notes:
32777
35268
  retrievalScope: typeof omConfig.retrieval === "object" ? omConfig.retrieval.scope ?? "resource" : "resource",
32778
35269
  searchEnabled: this.hasRetrievalSearch(omConfig.retrieval)
32779
35270
  });
35271
+ if (omConfig?.experimental_subconscious instanceof Subconscious && omConfig.experimental_subconscious.resolved.tools) Object.assign(tools, createKnowledgeTools(this));
32780
35272
  return tools;
32781
35273
  }
32782
35274
  /**
@@ -33257,6 +35749,8 @@ Notes:
33257
35749
  if (om) processors.push(om);
33258
35750
  const wm = await this.createWorkingMemoryStateProcessor(configuredProcessors, context);
33259
35751
  if (wm) processors.push(wm);
35752
+ const pins = await this.createPinnedStateProcessor(configuredProcessors, context);
35753
+ if (pins) processors.push(pins);
33260
35754
  return processors;
33261
35755
  }
33262
35756
  /**
@@ -33304,6 +35798,21 @@ Notes:
33304
35798
  if (configuredProcessors.some((p) => !("workflow" in p) && p.id === WORKING_MEMORY_STATE_PROCESSOR_ID)) return null;
33305
35799
  return new WorkingMemoryStateProcessor(this, runtimeMemory?.memoryConfig);
33306
35800
  }
35801
+ /**
35802
+ * Creates a PinnedStateProcessor when Subconscious pins are enabled on the
35803
+ * merged thread config. The gate is the validated `resolved.pins` on the
35804
+ * Subconscious instance, never the raw user object. Returns null when pins
35805
+ * are off or the processor is already present in the user's configured
35806
+ * processors.
35807
+ */
35808
+ async createPinnedStateProcessor(configuredProcessors = [], context) {
35809
+ const runtimeMemory = context?.get("MastraMemory");
35810
+ const subconscious = normalizeObservationalMemoryConfig(this.getMergedThreadConfig(runtimeMemory?.memoryConfig).observationalMemory)?.experimental_subconscious;
35811
+ if (!(subconscious instanceof Subconscious) || subconscious.resolved.pins === false) return null;
35812
+ const { PinnedStateProcessor, SUBCONSCIOUS_PINS_STATE_ID } = await Promise.resolve().then(() => subconscious_exports);
35813
+ if (configuredProcessors.some((p) => !("workflow" in p) && p.id === SUBCONSCIOUS_PINS_STATE_ID)) return null;
35814
+ return new PinnedStateProcessor({ getKnowledgeStore: () => this.storage.getStore("knowledge") });
35815
+ }
33307
35816
  };
33308
35817
  //#endregion
33309
35818
  //#region ../agent-builder/dist/index.js
@@ -34093,23 +36602,23 @@ const createModelInstance = async (provider, modelId, version = "v2") => {
34093
36602
  try {
34094
36603
  const providerFn = version === `v1` ? { v1: {
34095
36604
  openai: async () => {
34096
- const { openai } = await import("./dist-DyBO3IVt.js");
36605
+ const { openai } = await import("./dist-bAFqx06T.js");
34097
36606
  return openai(modelId);
34098
36607
  },
34099
36608
  anthropic: async () => {
34100
- const { anthropic } = await import("./dist-JdnTASYe.js");
36609
+ const { anthropic } = await import("./dist-CscF1cF8.js");
34101
36610
  return anthropic(modelId);
34102
36611
  },
34103
36612
  groq: async () => {
34104
- const { groq } = await import("./dist-BD0I5lxM.js");
36613
+ const { groq } = await import("./dist-CHJcZQdS.js");
34105
36614
  return groq(modelId);
34106
36615
  },
34107
36616
  xai: async () => {
34108
- const { xai } = await import("./dist-C-9xUY65.js");
36617
+ const { xai } = await import("./dist-Jn3uXsoB.js");
34109
36618
  return xai(modelId);
34110
36619
  },
34111
36620
  google: async () => {
34112
- const { google } = await import("./dist-sUhxlnJz.js");
36621
+ const { google } = await import("./dist-CRgxcDTg.js");
34113
36622
  return google(modelId);
34114
36623
  }
34115
36624
  } }[version][provider] : () => new ModelRouterLanguageModel(`${provider}/${modelId}`);
@@ -43687,4 +46196,4 @@ const agentBuilderWorkflows = {
43687
46196
  //#endregion
43688
46197
  export { agentBuilderWorkflows };
43689
46198
 
43690
- //# sourceMappingURL=dist-CpxQhZED.js.map
46199
+ //# sourceMappingURL=dist-Cw-T1gX6.js.map