@theokit/sdk 5.15.0 → 5.15.2

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 (368) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/a2a/index.cjs +3 -3
  3. package/dist/a2a/index.js +1 -1
  4. package/dist/{agent-B6FQad6P.d.cts → agent-BL4kxgwq.d.cts} +7 -1
  5. package/dist/{agent-B6C9i_qu.d.ts → agent-ByDx7K30.d.ts} +7 -1
  6. package/dist/agent-D6WBBNGR.cjs +72 -0
  7. package/dist/{agent-VI2HITPT.cjs.map → agent-D6WBBNGR.cjs.map} +1 -1
  8. package/dist/agent-QRIFX2SY.js +63 -0
  9. package/dist/{agent-DRDGUU6T.js.map → agent-QRIFX2SY.js.map} +1 -1
  10. package/dist/agent-session-store-2LQEPS4H.js +6 -0
  11. package/dist/{agent-session-store-22GKA7O4.js.map → agent-session-store-2LQEPS4H.js.map} +1 -1
  12. package/dist/agent-session-store-IOH6BREF.cjs +23 -0
  13. package/dist/{agent-session-store-WP6NGDVX.cjs.map → agent-session-store-IOH6BREF.cjs.map} +1 -1
  14. package/dist/auth/index.cjs +15 -15
  15. package/dist/auth/index.js +3 -3
  16. package/dist/{batch-N2XDYZED.js → batch-7IGV2OKA.js} +8 -8
  17. package/dist/{batch-N2XDYZED.js.map → batch-7IGV2OKA.js.map} +1 -1
  18. package/dist/{batch-VFR2MAUE.cjs → batch-FIWQZ3JD.cjs} +14 -14
  19. package/dist/{batch-VFR2MAUE.cjs.map → batch-FIWQZ3JD.cjs.map} +1 -1
  20. package/dist/{chunk-AT2PESXB.cjs → chunk-2UYAL4N7.cjs} +5 -5
  21. package/dist/chunk-2UYAL4N7.cjs.map +1 -0
  22. package/dist/{chunk-K2BQQ445.js → chunk-3GQYMKVJ.js} +3 -3
  23. package/dist/{chunk-K2BQQ445.js.map → chunk-3GQYMKVJ.js.map} +1 -1
  24. package/dist/{chunk-YSTXFWQE.cjs → chunk-3HL43XBD.cjs} +4 -4
  25. package/dist/{chunk-YSTXFWQE.cjs.map → chunk-3HL43XBD.cjs.map} +1 -1
  26. package/dist/{chunk-XESYJ4JC.js → chunk-3VX7JHJI.js} +7 -7
  27. package/dist/{chunk-XESYJ4JC.js.map → chunk-3VX7JHJI.js.map} +1 -1
  28. package/dist/{chunk-6XQLTQB6.cjs → chunk-3YCNBOX7.cjs} +3 -3
  29. package/dist/{chunk-6XQLTQB6.cjs.map → chunk-3YCNBOX7.cjs.map} +1 -1
  30. package/dist/{chunk-CHKV2L2Y.cjs → chunk-46YYJIHL.cjs} +30 -30
  31. package/dist/chunk-46YYJIHL.cjs.map +1 -0
  32. package/dist/{chunk-73IITAF7.js → chunk-4C37ELQL.js} +9 -9
  33. package/dist/{chunk-73IITAF7.js.map → chunk-4C37ELQL.js.map} +1 -1
  34. package/dist/{chunk-AGO5S5WD.js → chunk-4E4D6H77.js} +3 -3
  35. package/dist/{chunk-AGO5S5WD.js.map → chunk-4E4D6H77.js.map} +1 -1
  36. package/dist/{chunk-R35ZJAYT.cjs → chunk-4JF52NED.cjs} +12 -12
  37. package/dist/{chunk-R35ZJAYT.cjs.map → chunk-4JF52NED.cjs.map} +1 -1
  38. package/dist/{chunk-INVEGVGO.js → chunk-4TA47IK4.js} +8 -8
  39. package/dist/{chunk-INVEGVGO.js.map → chunk-4TA47IK4.js.map} +1 -1
  40. package/dist/{chunk-MLGETTYX.js → chunk-4YUIYSZO.js} +6 -6
  41. package/dist/{chunk-MLGETTYX.js.map → chunk-4YUIYSZO.js.map} +1 -1
  42. package/dist/{chunk-RZL2W4C3.js → chunk-5L7S2VOL.js} +5 -5
  43. package/dist/{chunk-RZL2W4C3.js.map → chunk-5L7S2VOL.js.map} +1 -1
  44. package/dist/{chunk-3WKWBYPO.cjs → chunk-6EHOJLJ3.cjs} +20 -20
  45. package/dist/chunk-6EHOJLJ3.cjs.map +1 -0
  46. package/dist/{chunk-XOU3CL7S.cjs → chunk-6HQFPX7N.cjs} +28 -28
  47. package/dist/chunk-6HQFPX7N.cjs.map +1 -0
  48. package/dist/{chunk-DJKGDLYZ.cjs → chunk-6XT5LAZG.cjs} +126 -59
  49. package/dist/chunk-6XT5LAZG.cjs.map +1 -0
  50. package/dist/{chunk-R427EOZE.cjs → chunk-7EFT6N5C.cjs} +13 -13
  51. package/dist/{chunk-R427EOZE.cjs.map → chunk-7EFT6N5C.cjs.map} +1 -1
  52. package/dist/{chunk-L7V4DDIE.cjs → chunk-7VNFOGRD.cjs} +12 -12
  53. package/dist/chunk-7VNFOGRD.cjs.map +1 -0
  54. package/dist/{chunk-YKNBTHMD.js → chunk-AQ23NII7.js} +3 -3
  55. package/dist/{chunk-YKNBTHMD.js.map → chunk-AQ23NII7.js.map} +1 -1
  56. package/dist/{chunk-ARC2V7NY.js → chunk-ATGSV4GS.js} +4 -4
  57. package/dist/{chunk-ARC2V7NY.js.map → chunk-ATGSV4GS.js.map} +1 -1
  58. package/dist/{chunk-H7HD6RXO.cjs → chunk-AW72G4TC.cjs} +5 -5
  59. package/dist/{chunk-H7HD6RXO.cjs.map → chunk-AW72G4TC.cjs.map} +1 -1
  60. package/dist/{chunk-M4U24U6G.js → chunk-AZK3QM36.js} +5 -5
  61. package/dist/{chunk-M4U24U6G.js.map → chunk-AZK3QM36.js.map} +1 -1
  62. package/dist/{chunk-QK2ERTO3.js → chunk-BH6M2DGV.js} +4 -4
  63. package/dist/{chunk-QK2ERTO3.js.map → chunk-BH6M2DGV.js.map} +1 -1
  64. package/dist/{chunk-64ECM3XM.cjs → chunk-BTGYRM4J.cjs} +264 -264
  65. package/dist/chunk-BTGYRM4J.cjs.map +1 -0
  66. package/dist/{chunk-5M5GQYBM.js → chunk-CG64VPPU.js} +50 -50
  67. package/dist/{chunk-5M5GQYBM.js.map → chunk-CG64VPPU.js.map} +1 -1
  68. package/dist/{chunk-CBBT42VX.js → chunk-CMDM4VF6.js} +3 -3
  69. package/dist/{chunk-CBBT42VX.js.map → chunk-CMDM4VF6.js.map} +1 -1
  70. package/dist/{chunk-OLJOI4LK.js → chunk-CN732Z5C.js} +4 -4
  71. package/dist/{chunk-OLJOI4LK.js.map → chunk-CN732Z5C.js.map} +1 -1
  72. package/dist/{chunk-SETHRLQS.cjs → chunk-D3BL3EEB.cjs} +9 -9
  73. package/dist/chunk-D3BL3EEB.cjs.map +1 -0
  74. package/dist/{chunk-LCCT5ZXJ.js → chunk-DB5RYCXX.js} +13 -13
  75. package/dist/{chunk-LCCT5ZXJ.js.map → chunk-DB5RYCXX.js.map} +1 -1
  76. package/dist/{chunk-SV63WTA2.js → chunk-DBH2WA2U.js} +4 -4
  77. package/dist/{chunk-SV63WTA2.js.map → chunk-DBH2WA2U.js.map} +1 -1
  78. package/dist/{chunk-XE3CAY6Z.cjs → chunk-DEHPRORL.cjs} +4 -4
  79. package/dist/{chunk-XE3CAY6Z.cjs.map → chunk-DEHPRORL.cjs.map} +1 -1
  80. package/dist/{chunk-UKMBRMGT.js → chunk-DGO4LPLP.js} +4 -4
  81. package/dist/{chunk-UKMBRMGT.js.map → chunk-DGO4LPLP.js.map} +1 -1
  82. package/dist/{chunk-RS7YQR4X.cjs → chunk-EBX6XUN7.cjs} +7 -7
  83. package/dist/{chunk-RS7YQR4X.cjs.map → chunk-EBX6XUN7.cjs.map} +1 -1
  84. package/dist/chunk-EDIYR4VR.cjs +18 -0
  85. package/dist/{chunk-SPEN7RJU.cjs.map → chunk-EDIYR4VR.cjs.map} +1 -1
  86. package/dist/{chunk-QGDPMM3C.js → chunk-EF5IONLL.js} +5 -5
  87. package/dist/{chunk-QGDPMM3C.js.map → chunk-EF5IONLL.js.map} +1 -1
  88. package/dist/{chunk-MSW7LB2V.cjs → chunk-EOWIUDKG.cjs} +5 -5
  89. package/dist/{chunk-MSW7LB2V.cjs.map → chunk-EOWIUDKG.cjs.map} +1 -1
  90. package/dist/{chunk-L7JPXZ2C.cjs → chunk-ER3BF23R.cjs} +19 -19
  91. package/dist/{chunk-L7JPXZ2C.cjs.map → chunk-ER3BF23R.cjs.map} +1 -1
  92. package/dist/{chunk-BNEUB52I.cjs → chunk-ERBKPA2N.cjs} +4 -4
  93. package/dist/{chunk-BNEUB52I.cjs.map → chunk-ERBKPA2N.cjs.map} +1 -1
  94. package/dist/{chunk-4QCJAJAG.js → chunk-F54PXZIA.js} +5 -5
  95. package/dist/{chunk-4QCJAJAG.js.map → chunk-F54PXZIA.js.map} +1 -1
  96. package/dist/{chunk-2XWAYCFM.cjs → chunk-FBT2SF2S.cjs} +12 -12
  97. package/dist/{chunk-2XWAYCFM.cjs.map → chunk-FBT2SF2S.cjs.map} +1 -1
  98. package/dist/{chunk-AUH2EVWY.cjs → chunk-FZSPVIFK.cjs} +16 -16
  99. package/dist/chunk-FZSPVIFK.cjs.map +1 -0
  100. package/dist/{chunk-CYWOJA6B.js → chunk-GA27FFT5.js} +3 -3
  101. package/dist/{chunk-CYWOJA6B.js.map → chunk-GA27FFT5.js.map} +1 -1
  102. package/dist/{chunk-HWMGR3HA.js → chunk-GEQLHBJM.js} +6 -6
  103. package/dist/{chunk-HWMGR3HA.js.map → chunk-GEQLHBJM.js.map} +1 -1
  104. package/dist/{chunk-IJ7M6GOG.cjs → chunk-GKERJ52A.cjs} +4 -4
  105. package/dist/{chunk-IJ7M6GOG.cjs.map → chunk-GKERJ52A.cjs.map} +1 -1
  106. package/dist/{chunk-NEH3BPFD.cjs → chunk-HI5TJWQE.cjs} +19 -19
  107. package/dist/{chunk-NEH3BPFD.cjs.map → chunk-HI5TJWQE.cjs.map} +1 -1
  108. package/dist/{chunk-ZOFRNNZD.cjs → chunk-IZV72OEI.cjs} +11 -11
  109. package/dist/chunk-IZV72OEI.cjs.map +1 -0
  110. package/dist/{chunk-KU5O7WPK.js → chunk-JD3EKKKB.js} +4 -4
  111. package/dist/{chunk-KU5O7WPK.js.map → chunk-JD3EKKKB.js.map} +1 -1
  112. package/dist/{chunk-DFBWYETS.js → chunk-JRP2W2DR.js} +3 -3
  113. package/dist/{chunk-DFBWYETS.js.map → chunk-JRP2W2DR.js.map} +1 -1
  114. package/dist/{chunk-IOBHFP2E.js → chunk-JRQJMZKY.js} +82 -15
  115. package/dist/chunk-JRQJMZKY.js.map +1 -0
  116. package/dist/{chunk-YQ3XC6C2.cjs → chunk-JVH3NNJ3.cjs} +13 -13
  117. package/dist/chunk-JVH3NNJ3.cjs.map +1 -0
  118. package/dist/{chunk-VWYFGE27.cjs → chunk-KC2HKUPT.cjs} +56 -56
  119. package/dist/chunk-KC2HKUPT.cjs.map +1 -0
  120. package/dist/{chunk-PDOXYXWX.cjs → chunk-KDJTECE6.cjs} +4 -4
  121. package/dist/{chunk-PDOXYXWX.cjs.map → chunk-KDJTECE6.cjs.map} +1 -1
  122. package/dist/{chunk-QD6B6W6I.js → chunk-L2KC2G7H.js} +5 -5
  123. package/dist/{chunk-QD6B6W6I.js.map → chunk-L2KC2G7H.js.map} +1 -1
  124. package/dist/{chunk-3BBTHFGJ.js → chunk-L5B7EWWH.js} +5 -5
  125. package/dist/{chunk-3BBTHFGJ.js.map → chunk-L5B7EWWH.js.map} +1 -1
  126. package/dist/{chunk-X7CE7Y5W.js → chunk-LG4JCJEI.js} +11 -11
  127. package/dist/{chunk-X7CE7Y5W.js.map → chunk-LG4JCJEI.js.map} +1 -1
  128. package/dist/{chunk-2HXTNVLM.js → chunk-LSURFRJA.js} +6 -6
  129. package/dist/{chunk-2HXTNVLM.js.map → chunk-LSURFRJA.js.map} +1 -1
  130. package/dist/{chunk-55LLQFHW.cjs → chunk-MJGY3E3C.cjs} +4 -4
  131. package/dist/{chunk-55LLQFHW.cjs.map → chunk-MJGY3E3C.cjs.map} +1 -1
  132. package/dist/{chunk-EQ5IDL6W.cjs → chunk-MKS5FFH5.cjs} +15 -15
  133. package/dist/chunk-MKS5FFH5.cjs.map +1 -0
  134. package/dist/{chunk-WM646HEN.js → chunk-MTNCJ7MQ.js} +6 -6
  135. package/dist/{chunk-WM646HEN.js.map → chunk-MTNCJ7MQ.js.map} +1 -1
  136. package/dist/{chunk-SA6K24NB.cjs → chunk-MXJJMP4U.cjs} +7 -7
  137. package/dist/chunk-MXJJMP4U.cjs.map +1 -0
  138. package/dist/{chunk-FTXY4D44.cjs → chunk-N2ORTDSO.cjs} +20 -20
  139. package/dist/chunk-N2ORTDSO.cjs.map +1 -0
  140. package/dist/{chunk-7YUPSBDV.cjs → chunk-NDXZXGVP.cjs} +6 -6
  141. package/dist/{chunk-7YUPSBDV.cjs.map → chunk-NDXZXGVP.cjs.map} +1 -1
  142. package/dist/{chunk-3UMPP553.cjs → chunk-NMRNE6QX.cjs} +11 -11
  143. package/dist/{chunk-3UMPP553.cjs.map → chunk-NMRNE6QX.cjs.map} +1 -1
  144. package/dist/{chunk-PKRPV3R7.js → chunk-NO6AG22P.js} +6 -6
  145. package/dist/{chunk-PKRPV3R7.js.map → chunk-NO6AG22P.js.map} +1 -1
  146. package/dist/{chunk-NK5EOTDY.js → chunk-OIOSY5G6.js} +3 -3
  147. package/dist/{chunk-NK5EOTDY.js.map → chunk-OIOSY5G6.js.map} +1 -1
  148. package/dist/{chunk-RGVMJU57.js → chunk-P7B64NFK.js} +8 -8
  149. package/dist/{chunk-RGVMJU57.js.map → chunk-P7B64NFK.js.map} +1 -1
  150. package/dist/{chunk-TDED5XES.js → chunk-PCPYTBVV.js} +6 -6
  151. package/dist/chunk-PCPYTBVV.js.map +1 -0
  152. package/dist/{chunk-U7PRI3XM.cjs → chunk-PDFSLD5P.cjs} +6 -6
  153. package/dist/{chunk-U7PRI3XM.cjs.map → chunk-PDFSLD5P.cjs.map} +1 -1
  154. package/dist/{chunk-YMVTUV5K.js → chunk-PISZRLES.js} +5 -5
  155. package/dist/{chunk-YMVTUV5K.js.map → chunk-PISZRLES.js.map} +1 -1
  156. package/dist/{chunk-BUUUWQMB.cjs → chunk-PNL63WDP.cjs} +4 -4
  157. package/dist/{chunk-BUUUWQMB.cjs.map → chunk-PNL63WDP.cjs.map} +1 -1
  158. package/dist/{chunk-23SS4ID4.js → chunk-PSMWZYW6.js} +4 -4
  159. package/dist/{chunk-23SS4ID4.js.map → chunk-PSMWZYW6.js.map} +1 -1
  160. package/dist/{chunk-5645PMVU.cjs → chunk-PXYINWBC.cjs} +20 -20
  161. package/dist/chunk-PXYINWBC.cjs.map +1 -0
  162. package/dist/{chunk-RTDVSHJR.cjs → chunk-Q4UOCMAO.cjs} +5 -5
  163. package/dist/{chunk-RTDVSHJR.cjs.map → chunk-Q4UOCMAO.cjs.map} +1 -1
  164. package/dist/{chunk-5IRDK5BC.js → chunk-QH6MWGOA.js} +4 -4
  165. package/dist/{chunk-5IRDK5BC.js.map → chunk-QH6MWGOA.js.map} +1 -1
  166. package/dist/{chunk-3LMVJTNJ.js → chunk-QPUKIZOT.js} +3 -3
  167. package/dist/{chunk-3LMVJTNJ.js.map → chunk-QPUKIZOT.js.map} +1 -1
  168. package/dist/{chunk-SWALPLFQ.cjs → chunk-RTCO3USA.cjs} +16 -16
  169. package/dist/chunk-RTCO3USA.cjs.map +1 -0
  170. package/dist/{chunk-SAGRF4IB.js → chunk-S2CMEJ5F.js} +3 -3
  171. package/dist/{chunk-SAGRF4IB.js.map → chunk-S2CMEJ5F.js.map} +1 -1
  172. package/dist/{chunk-VZGE7NAI.js → chunk-S5ERB3CH.js} +3 -3
  173. package/dist/{chunk-VZGE7NAI.js.map → chunk-S5ERB3CH.js.map} +1 -1
  174. package/dist/{chunk-XJ3WU5CZ.js → chunk-S7IZEVXX.js} +6 -6
  175. package/dist/{chunk-XJ3WU5CZ.js.map → chunk-S7IZEVXX.js.map} +1 -1
  176. package/dist/{chunk-Q7UG242V.js → chunk-TIYQDJFK.js} +3 -3
  177. package/dist/{chunk-Q7UG242V.js.map → chunk-TIYQDJFK.js.map} +1 -1
  178. package/dist/{chunk-POBZXULR.cjs → chunk-TTNJOM5W.cjs} +16 -16
  179. package/dist/{chunk-POBZXULR.cjs.map → chunk-TTNJOM5W.cjs.map} +1 -1
  180. package/dist/{chunk-VCQ37TC5.js → chunk-TTXRNCXY.js} +3 -3
  181. package/dist/{chunk-VCQ37TC5.js.map → chunk-TTXRNCXY.js.map} +1 -1
  182. package/dist/{chunk-3HA7N2BB.cjs → chunk-TYKBAKAS.cjs} +5 -5
  183. package/dist/{chunk-3HA7N2BB.cjs.map → chunk-TYKBAKAS.cjs.map} +1 -1
  184. package/dist/{chunk-A77UMVMD.cjs → chunk-UMCCYXFZ.cjs} +8 -8
  185. package/dist/{chunk-A77UMVMD.cjs.map → chunk-UMCCYXFZ.cjs.map} +1 -1
  186. package/dist/{chunk-3GTN4HOO.js → chunk-UNP4NCMZ.js} +3 -3
  187. package/dist/{chunk-3GTN4HOO.js.map → chunk-UNP4NCMZ.js.map} +1 -1
  188. package/dist/{chunk-BPL5CVZ5.js → chunk-VFT63FJF.js} +3 -3
  189. package/dist/{chunk-BPL5CVZ5.js.map → chunk-VFT63FJF.js.map} +1 -1
  190. package/dist/{chunk-3KIUY67P.cjs → chunk-VHY6NVCJ.cjs} +30 -30
  191. package/dist/chunk-VHY6NVCJ.cjs.map +1 -0
  192. package/dist/{chunk-KMFBNKCT.cjs → chunk-VT3NWHFH.cjs} +6 -6
  193. package/dist/{chunk-KMFBNKCT.cjs.map → chunk-VT3NWHFH.cjs.map} +1 -1
  194. package/dist/{chunk-FJWQP6EE.js → chunk-WJ6OGKAO.js} +3 -3
  195. package/dist/{chunk-FJWQP6EE.js.map → chunk-WJ6OGKAO.js.map} +1 -1
  196. package/dist/{chunk-FLDHYF5C.cjs → chunk-X2XLSE2N.cjs} +9 -9
  197. package/dist/chunk-X2XLSE2N.cjs.map +1 -0
  198. package/dist/{chunk-UDAKAE4Z.cjs → chunk-X4ZYEZPD.cjs} +12 -12
  199. package/dist/chunk-X4ZYEZPD.cjs.map +1 -0
  200. package/dist/{chunk-QG4SXZ2A.cjs → chunk-XR6O6G3B.cjs} +27 -27
  201. package/dist/chunk-XR6O6G3B.cjs.map +1 -0
  202. package/dist/{chunk-BWYC7RZG.cjs → chunk-XTQWTVVI.cjs} +11 -11
  203. package/dist/chunk-XTQWTVVI.cjs.map +1 -0
  204. package/dist/{chunk-MLJDW2YK.js → chunk-YSGS57DA.js} +4 -4
  205. package/dist/{chunk-MLJDW2YK.js.map → chunk-YSGS57DA.js.map} +1 -1
  206. package/dist/{chunk-KCM3RMKR.js → chunk-YUQNHLKN.js} +8 -8
  207. package/dist/{chunk-KCM3RMKR.js.map → chunk-YUQNHLKN.js.map} +1 -1
  208. package/dist/{chunk-P7QYG4RZ.cjs → chunk-Z5MB2HAN.cjs} +8 -8
  209. package/dist/{chunk-P7QYG4RZ.cjs.map → chunk-Z5MB2HAN.cjs.map} +1 -1
  210. package/dist/{chunk-HJ2LV464.js → chunk-ZUWVO442.js} +4 -4
  211. package/dist/{chunk-HJ2LV464.js.map → chunk-ZUWVO442.js.map} +1 -1
  212. package/dist/{compact-session-NX7HUNTB.cjs → compact-session-5DWFHMW4.cjs} +21 -21
  213. package/dist/{compact-session-NX7HUNTB.cjs.map → compact-session-5DWFHMW4.cjs.map} +1 -1
  214. package/dist/{compact-session-Q5IGNFPW.js → compact-session-AL65PEMX.js} +12 -12
  215. package/dist/{compact-session-Q5IGNFPW.js.map → compact-session-AL65PEMX.js.map} +1 -1
  216. package/dist/context/index.cjs +11 -11
  217. package/dist/context/index.js +6 -6
  218. package/dist/context-4XSD2V3G.js +7 -0
  219. package/dist/{context-7EBZST3L.js.map → context-4XSD2V3G.js.map} +1 -1
  220. package/dist/context-ZX2VBGSX.cjs +24 -0
  221. package/dist/{context-4RSI3AXT.cjs.map → context-ZX2VBGSX.cjs.map} +1 -1
  222. package/dist/{cron-Bh3aWgQ2.d.cts → cron-B7KH9sHW.d.cts} +1 -1
  223. package/dist/{cron-CCDxeeFZ.d.ts → cron-FEO7UAQF.d.ts} +1 -1
  224. package/dist/cron.cjs +40 -40
  225. package/dist/cron.d.cts +2 -2
  226. package/dist/cron.d.ts +2 -2
  227. package/dist/cron.js +39 -39
  228. package/dist/eval.cjs +51 -51
  229. package/dist/eval.cjs.map +1 -1
  230. package/dist/eval.js +41 -41
  231. package/dist/{executor-THUXNAFR.js → executor-ZHIUSHRV.js} +7 -7
  232. package/dist/{executor-THUXNAFR.js.map → executor-ZHIUSHRV.js.map} +1 -1
  233. package/dist/{executor-5QL5AXIZ.cjs → executor-ZTLJZ5LK.cjs} +24 -24
  234. package/dist/{executor-5QL5AXIZ.cjs.map → executor-ZTLJZ5LK.cjs.map} +1 -1
  235. package/dist/filesystem/index.cjs +14 -14
  236. package/dist/filesystem/index.cjs.map +1 -1
  237. package/dist/filesystem/index.js +4 -4
  238. package/dist/{fork-agent-S2EPIML7.js → fork-agent-BHVTALT5.js} +3 -3
  239. package/dist/{fork-agent-S2EPIML7.js.map → fork-agent-BHVTALT5.js.map} +1 -1
  240. package/dist/{fork-agent-WAEQI2DL.cjs → fork-agent-DCOPPXM2.cjs} +4 -4
  241. package/dist/{fork-agent-WAEQI2DL.cjs.map → fork-agent-DCOPPXM2.cjs.map} +1 -1
  242. package/dist/fs-session-store-EZ32TFGB.js +11 -0
  243. package/dist/{fs-session-store-MYQEVUFL.js.map → fs-session-store-EZ32TFGB.js.map} +1 -1
  244. package/dist/fs-session-store-G664LDDN.cjs +20 -0
  245. package/dist/{fs-session-store-CYNTEPJZ.cjs.map → fs-session-store-G664LDDN.cjs.map} +1 -1
  246. package/dist/generate-object-JFZTK567.cjs +20 -0
  247. package/dist/{generate-object-A5F576IT.cjs.map → generate-object-JFZTK567.cjs.map} +1 -1
  248. package/dist/{generate-object-TBDOBBYW.js → generate-object-RPBXY2U3.js} +4 -4
  249. package/dist/{generate-object-TBDOBBYW.js.map → generate-object-RPBXY2U3.js.map} +1 -1
  250. package/dist/index-manager-2MJEEN2O.js +18 -0
  251. package/dist/{index-manager-NF2WRLOU.js.map → index-manager-2MJEEN2O.js.map} +1 -1
  252. package/dist/index-manager-CT6MMG7S.cjs +27 -0
  253. package/dist/{index-manager-2KH75BRW.cjs.map → index-manager-CT6MMG7S.cjs.map} +1 -1
  254. package/dist/index.cjs +130 -130
  255. package/dist/index.cjs.map +1 -1
  256. package/dist/index.d.cts +3 -3
  257. package/dist/index.d.ts +3 -3
  258. package/dist/index.js +56 -56
  259. package/dist/{inject-session-4ROYLZHY.js → inject-session-E2SZ4A35.js} +6 -6
  260. package/dist/{inject-session-4ROYLZHY.js.map → inject-session-E2SZ4A35.js.map} +1 -1
  261. package/dist/{inject-session-AWKDCGHV.cjs → inject-session-QZULG65O.cjs} +8 -8
  262. package/dist/{inject-session-AWKDCGHV.cjs.map → inject-session-QZULG65O.cjs.map} +1 -1
  263. package/dist/internal/llm/hermes-tool-extract.d.ts +2 -0
  264. package/dist/internal/memory/adapters/index.cjs +4 -4
  265. package/dist/internal/memory/adapters/index.js +3 -3
  266. package/dist/internal/memory/storage/index.cjs +45 -45
  267. package/dist/internal/memory/storage/index.js +9 -9
  268. package/dist/internal/persistence/index.cjs +22 -22
  269. package/dist/internal/persistence/index.js +6 -6
  270. package/dist/internal/security/index.cjs +9 -9
  271. package/dist/internal/security/index.js +2 -2
  272. package/dist/mcp-auth.cjs +8 -8
  273. package/dist/mcp-auth.js +3 -3
  274. package/dist/models.cjs +30 -30
  275. package/dist/models.cjs.map +1 -1
  276. package/dist/models.js +8 -8
  277. package/dist/{oauth-transaction-store-U34YLEGP.js → oauth-transaction-store-QQBWGNE2.js} +3 -3
  278. package/dist/{oauth-transaction-store-U34YLEGP.js.map → oauth-transaction-store-QQBWGNE2.js.map} +1 -1
  279. package/dist/{oauth-transaction-store-OMX436YB.cjs → oauth-transaction-store-YF7WOA6B.cjs} +10 -10
  280. package/dist/{oauth-transaction-store-OMX436YB.cjs.map → oauth-transaction-store-YF7WOA6B.cjs.map} +1 -1
  281. package/dist/path-safety.cjs +9 -9
  282. package/dist/path-safety.js +2 -2
  283. package/dist/persistence.cjs +41 -41
  284. package/dist/persistence.cjs.map +1 -1
  285. package/dist/persistence.js +11 -11
  286. package/dist/project.cjs +7 -7
  287. package/dist/project.cjs.map +1 -1
  288. package/dist/project.js +4 -4
  289. package/dist/providers.cjs +6 -6
  290. package/dist/providers.js +4 -4
  291. package/dist/{registry-5TDAF7RK.js → registry-DOYBR237.js} +6 -6
  292. package/dist/{registry-5TDAF7RK.js.map → registry-DOYBR237.js.map} +1 -1
  293. package/dist/{registry-W7TSCLQO.cjs → registry-PB7JFVUJ.cjs} +14 -14
  294. package/dist/{registry-W7TSCLQO.cjs.map → registry-PB7JFVUJ.cjs.map} +1 -1
  295. package/dist/sandbox/index.cjs +41 -41
  296. package/dist/sandbox/index.cjs.map +1 -1
  297. package/dist/sandbox/index.js +7 -7
  298. package/dist/sanitize/index.cjs +2 -2
  299. package/dist/sanitize/index.js +1 -1
  300. package/dist/server/auth/index.cjs +9 -9
  301. package/dist/server/auth/index.cjs.map +1 -1
  302. package/dist/server/auth/index.js +4 -4
  303. package/dist/{session-transcript-7TZ6HXSX.cjs → session-transcript-EBVGLZ6B.cjs} +17 -17
  304. package/dist/{session-transcript-7TZ6HXSX.cjs.map → session-transcript-EBVGLZ6B.cjs.map} +1 -1
  305. package/dist/{session-transcript-BSHZYYY6.js → session-transcript-GU2VE7JX.js} +4 -4
  306. package/dist/{session-transcript-BSHZYYY6.js.map → session-transcript-GU2VE7JX.js.map} +1 -1
  307. package/dist/skills.cjs +7 -7
  308. package/dist/skills.js +4 -4
  309. package/dist/stream-object-3AU7QDHT.js +7 -0
  310. package/dist/{stream-object-EKM4WGTI.js.map → stream-object-3AU7QDHT.js.map} +1 -1
  311. package/dist/stream-object-SLGR2KIA.cjs +20 -0
  312. package/dist/{stream-object-AS4YYM4B.cjs.map → stream-object-SLGR2KIA.cjs.map} +1 -1
  313. package/dist/subagents-loader-4PQS7ULK.cjs +16 -0
  314. package/dist/{subagents-loader-KLWF4QPD.cjs.map → subagents-loader-4PQS7ULK.cjs.map} +1 -1
  315. package/dist/subagents-loader-CPFVLWLH.js +7 -0
  316. package/dist/{subagents-loader-SXETS2F2.js.map → subagents-loader-CPFVLWLH.js.map} +1 -1
  317. package/dist/subagents-loader.cjs +4 -4
  318. package/dist/subagents-loader.d.cts +1 -1
  319. package/dist/subagents-loader.d.ts +1 -1
  320. package/dist/subagents-loader.js +3 -3
  321. package/dist/subagents.cjs +2 -2
  322. package/dist/subagents.js +1 -1
  323. package/dist/task-store.cjs +5 -5
  324. package/dist/task-store.js +2 -2
  325. package/dist/types/hooks.d.ts +7 -1
  326. package/dist/workflow.cjs +28 -28
  327. package/dist/workflow.js +5 -5
  328. package/package.json +1 -1
  329. package/dist/agent-DRDGUU6T.js +0 -63
  330. package/dist/agent-VI2HITPT.cjs +0 -72
  331. package/dist/agent-session-store-22GKA7O4.js +0 -6
  332. package/dist/agent-session-store-WP6NGDVX.cjs +0 -23
  333. package/dist/chunk-3KIUY67P.cjs.map +0 -1
  334. package/dist/chunk-3WKWBYPO.cjs.map +0 -1
  335. package/dist/chunk-5645PMVU.cjs.map +0 -1
  336. package/dist/chunk-64ECM3XM.cjs.map +0 -1
  337. package/dist/chunk-AT2PESXB.cjs.map +0 -1
  338. package/dist/chunk-AUH2EVWY.cjs.map +0 -1
  339. package/dist/chunk-BWYC7RZG.cjs.map +0 -1
  340. package/dist/chunk-CHKV2L2Y.cjs.map +0 -1
  341. package/dist/chunk-DJKGDLYZ.cjs.map +0 -1
  342. package/dist/chunk-EQ5IDL6W.cjs.map +0 -1
  343. package/dist/chunk-FLDHYF5C.cjs.map +0 -1
  344. package/dist/chunk-FTXY4D44.cjs.map +0 -1
  345. package/dist/chunk-IOBHFP2E.js.map +0 -1
  346. package/dist/chunk-L7V4DDIE.cjs.map +0 -1
  347. package/dist/chunk-QG4SXZ2A.cjs.map +0 -1
  348. package/dist/chunk-SA6K24NB.cjs.map +0 -1
  349. package/dist/chunk-SETHRLQS.cjs.map +0 -1
  350. package/dist/chunk-SPEN7RJU.cjs +0 -18
  351. package/dist/chunk-SWALPLFQ.cjs.map +0 -1
  352. package/dist/chunk-TDED5XES.js.map +0 -1
  353. package/dist/chunk-UDAKAE4Z.cjs.map +0 -1
  354. package/dist/chunk-VWYFGE27.cjs.map +0 -1
  355. package/dist/chunk-XOU3CL7S.cjs.map +0 -1
  356. package/dist/chunk-YQ3XC6C2.cjs.map +0 -1
  357. package/dist/chunk-ZOFRNNZD.cjs.map +0 -1
  358. package/dist/context-4RSI3AXT.cjs +0 -24
  359. package/dist/context-7EBZST3L.js +0 -7
  360. package/dist/fs-session-store-CYNTEPJZ.cjs +0 -20
  361. package/dist/fs-session-store-MYQEVUFL.js +0 -11
  362. package/dist/generate-object-A5F576IT.cjs +0 -20
  363. package/dist/index-manager-2KH75BRW.cjs +0 -27
  364. package/dist/index-manager-NF2WRLOU.js +0 -18
  365. package/dist/stream-object-AS4YYM4B.cjs +0 -20
  366. package/dist/stream-object-EKM4WGTI.js +0 -7
  367. package/dist/subagents-loader-KLWF4QPD.cjs +0 -16
  368. package/dist/subagents-loader-SXETS2F2.js +0 -7
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/internal/persistence/sqlite-wal.ts","../src/internal/persistence/sqlite-open.ts"],"names":["diag","mkdir","dirname","ConfigurationError","rename"],"mappings":"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","file":"chunk-AT2PESXB.cjs","sourcesContent":["/**\n * SQLite WAL mode helper with NFS/SMB/FUSE fallback to DELETE (ADR D63).\n *\n * WAL is faster (concurrent readers + one writer) but unsupported on some\n * network/FUSE filesystems. Try WAL; if the pragma returns something else\n * or throws, fall back to DELETE journal mode. Warn one time per label.\n *\n * This block is the MODULE header and must stay at offset 0. Sitting below the import it became a\n * leading comment of the first declaration instead, which is how its tag deleted `PragmaCapable`\n * from the emitted `.d.ts` while `applyWalWithFallback` — which names it — survived.\n */\n\nimport { diag } from \"../diagnostics.js\";\n\n/**\n * The narrow slice of a SQLite handle this module needs: anything with a `pragma()` method, which\n * `better-sqlite3` satisfies without being named here.\n *\n * Not exported, but it appears in the signature of `applyWalWithFallback`, so it is emitted into\n * the published declarations and a consumer can structurally satisfy it.\n */\ninterface PragmaCapable {\n pragma: (statement: string, options?: { simple?: boolean }) => unknown;\n}\n\n/**\n * What journal mode a connection ended up in after `applyWalWithFallback`.\n *\n * `mode` is the mode actually in effect, never the one that was requested. `fellBack` is `true`\n * only when WAL was attempted and refused — either the pragma threw or it reported a mode other\n * than `wal` — and the connection was put into DELETE instead.\n *\n * `fellBack: true` is normal on NFS, SMB and FUSE, where WAL needs shared memory the filesystem\n * does not provide. It is not an error and nothing further is required of the caller; the\n * consequence is slower concurrent access, since DELETE mode does not allow readers alongside a\n * writer. Treat it as a signal about the storage, not about the database.\n *\n * @public — re-exported from the semver-protected `@theokit/sdk/persistence` barrel, and (for\n * back-compat) from the semver-exempt `@theokit/sdk/internal/persistence` alias.\n */\nexport interface WalApplyResult {\n /** Final journal_mode actually in effect. */\n mode: \"wal\" | \"delete\";\n /** True if we wanted WAL but the filesystem refused. */\n fellBack: boolean;\n}\n\nconst warnedLabels = new Set<string>();\n\n/**\n * Apply WAL mode with DELETE fallback. Idempotent — safe to call multiple\n * times on the same connection.\n *\n * @param db any `pragma()`-capable SQLite handle (e.g., `better-sqlite3`)\n * @param label short identifier used in the warning (e.g., \"memory-index\")\n *\n */\nexport function applyWalWithFallback(db: PragmaCapable, label: string): WalApplyResult {\n try {\n const result = db.pragma(\"journal_mode = WAL\", { simple: true });\n if (typeof result === \"string\" && result.toLowerCase() === \"wal\") {\n return { mode: \"wal\", fellBack: false };\n }\n logFallback(label, `got \"${String(result)}\" instead of \"wal\"`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logFallback(label, msg);\n }\n\n db.pragma(\"journal_mode = DELETE\");\n return { mode: \"delete\", fellBack: true };\n}\n\nfunction logFallback(label: string, reason: string): void {\n if (warnedLabels.has(label)) return;\n warnedLabels.add(label);\n diag(\n `[theokit-sdk] ${label}: WAL unavailable (${reason}); using DELETE journal mode. ` +\n \"This is normal on NFS/SMB/FUSE; expect slightly slower concurrent access.\\n\",\n );\n}\n\n/**\n * Test helper — clears the warn-once registry.\n *\n * @internal\n */\nexport function _resetWalWarnings(): void {\n warnedLabels.clear();\n}\n","/**\n * Resilient SQLite open (plan m0-foundation-expose-primitives, M0-5).\n *\n * Generalizes the driver-load + WAL-apply + corruption-recovery logic that was\n * duplicated (byte-identical) across `sdk/internal/memory/index-db.ts` and\n * `sdk-memory/internal/index/index-db.ts`. Schema-agnostic: the caller applies\n * its own PRAGMA/SCHEMA via the `onOpen` callback.\n *\n * Corruption recovery (EC-7): when opening fails with a \"malformed\" / \"not a\n * database\" / \"encrypted\" error and `recoverCorrupt` is not false, the file is\n * renamed aside to `<path>.corrupt-<ts>` (plus its WAL/SHM siblings) and a fresh\n * DB is opened. The corrupt file is renamed, NOT backed up — the timestamped\n * `.corrupt-*` file is kept for manual recovery.\n *\n * @internal — public via `@theokit/sdk/internal/persistence` (semver-exempt)\n */\n\nimport { mkdir, rename } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\nimport { ConfigurationError } from \"../../errors.js\";\nimport { diag } from \"../diagnostics.js\";\nimport { applyWalWithFallback } from \"./sqlite-wal.js\";\n\n/** Minimal SQLite handle surface every driver (`better-sqlite3`) exposes. */\nexport interface ResilientSqliteDb {\n /** SQLite `pragma()` access (used by `applyWalWithFallback`). */\n pragma(statement: string, options?: { simple?: boolean }): unknown;\n exec(sql: string): void;\n close(): void;\n}\n\n/**\n * Input to {@link openSqliteResilient}.\n *\n * The trap is `recoverCorrupt`, whose default is ON. When the driver reports a corrupt or encrypted\n * database, the file is renamed aside and a FRESH one is opened — so the call SUCCEEDS and hands\n * back an EMPTY database. The old bytes survive on disk under the renamed path, but a caller that\n * treats a resolved promise as \"my data is here\" is wrong exactly when it matters. Pass\n * `recoverCorrupt: false` to get the corruption error thrown instead.\n *\n * Semver-exempt: reachable via the '@theokit/sdk/internal/persistence' sub-path, which the package\n * declares in 'exports' but does NOT cover with its semver contract.\n *\n * @typeParam T - the concrete DB handle the driver returns; defaults to {@link ResilientSqliteDb}\n */\nexport interface OpenSqliteResilientOptions<T extends ResilientSqliteDb> {\n /** Absolute path to the SQLite file. Parent directories are created. */\n filePath: string;\n /**\n * Called after the driver is open and WAL is applied, before the handle is\n * returned. Apply PRAGMA/SCHEMA statements here. Errors propagate.\n */\n onOpen?: (db: T) => void | Promise<void>;\n /** Label used in the WAL-fallback warning and corruption-recovery log. Default \"sqlite\". */\n label?: string;\n /** When true (default) a corruption error renames the file aside and rebuilds. */\n recoverCorrupt?: boolean;\n}\n\n/**\n * Open a SQLite file with WAL (+ DELETE fallback) and corruption recovery.\n *\n * @typeParam T - the concrete DB handle type the driver returns (defaults to the\n * minimal {@link ResilientSqliteDb} surface)\n */\nexport async function openSqliteResilient<T extends ResilientSqliteDb = ResilientSqliteDb>(\n options: OpenSqliteResilientOptions<T>,\n): Promise<T> {\n await mkdir(dirname(options.filePath), { recursive: true });\n try {\n return await openConcrete(options);\n } catch (cause) {\n if (options.recoverCorrupt !== false && isCorruptionError(cause)) {\n await renameAside(options.filePath, options.label ?? \"sqlite\");\n return await openConcrete(options);\n }\n throw cause;\n }\n}\n\nasync function openConcrete<T extends ResilientSqliteDb>(\n options: OpenSqliteResilientOptions<T>,\n): Promise<T> {\n const db = await loadDriver<T>(options.filePath);\n // Apply WAL with NFS/SMB/FUSE fallback BEFORE schema so the journal mode is\n // set for the whole session.\n applyWalWithFallback(db, options.label ?? \"sqlite\");\n await options.onOpen?.(db);\n return db;\n}\n\n/** Injectable driver loaders (tests simulate a consumer env without better-sqlite3). */\ninterface DriverLoaders {\n betterSqlite3?: () => Promise<unknown>;\n nodeSqlite?: () => Promise<unknown>;\n}\nlet driverLoaderOverrides: DriverLoaders | undefined;\n\n/** Test-only. @internal */\nexport function _setDriverLoadersForTests(overrides: DriverLoaders | undefined): void {\n driverLoaderOverrides = overrides;\n}\n\n/**\n * Adapt `node:sqlite`'s `DatabaseSync` to the better-sqlite3 surface this module's callers use\n * (`prepare/get/all/run`, `exec`, `close`, `pragma`, `loadExtension`). The error message below has\n * ALWAYS promised this fallback (\"or run on Node 22.5+ for built-in node:sqlite\") — before the\n * flicker-bug fix the promise was fabricated: only better-sqlite3 was ever tried, so every consumer\n * without the optional native dep lost memory tools AND got a per-turn stderr WARN.\n */\nfunction adaptNodeSqlite(db: {\n prepare(sql: string): unknown;\n exec(sql: string): void;\n close(): void;\n loadExtension?: (path: string) => void;\n}): ResilientSqliteDb {\n const pragma = (statement: string, options?: { simple?: boolean }): unknown => {\n const stmt = db.prepare(`PRAGMA ${statement}`) as {\n get(): Record<string, unknown> | undefined;\n };\n const row = stmt.get();\n if (options?.simple === true) {\n return row === undefined ? undefined : Object.values(row)[0];\n }\n return row === undefined ? [] : [row];\n };\n return new Proxy(db as unknown as ResilientSqliteDb, {\n get(target, prop, receiver) {\n if (prop === \"pragma\") return pragma;\n // Reached by `sqlite-vec`'s own `load()`, not by anything in this package — see the member's\n // docblock on `MemoryDb`. `loadSqliteVecExtension` catches this and re-throws it as a\n // ConfigurationError with code `sqlite_vec_unavailable`, so a bare Error never escapes.\n if (prop === \"loadExtension\" && typeof db.loadExtension !== \"function\") {\n return () => {\n throw new Error(\n \"SQLite extension loading is unavailable on the node:sqlite fallback — install better-sqlite3 for sqlite-vec\",\n );\n };\n }\n const value = Reflect.get(target, prop, receiver) as unknown;\n return typeof value === \"function\"\n ? (value as (...a: unknown[]) => unknown).bind(target)\n : value;\n },\n });\n}\n\n// PRE-EXISTING debt, exposed when M75 fixed the Biome config that used to abort before\n// sweeping these files (a nested root under refactor/). It is not new code and was not touched\n// by M75; refactoring SDK internals without review would trade a visible problem for a diff\n// risky. Tracked in usetheodev/theokit-sdk#151.\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: see the reason just above\nasync function loadDriver<T extends ResilientSqliteDb>(filePath: string): Promise<T> {\n let betterSqliteCause: unknown;\n try {\n const mod = (await (driverLoaderOverrides?.betterSqlite3?.() ?? import(\"better-sqlite3\"))) as {\n default?: unknown;\n };\n const Ctor = mod.default ?? mod;\n if (typeof Ctor !== \"function\") {\n throw new Error(`better-sqlite3 export is not a constructor (got ${typeof Ctor})`);\n }\n return new (Ctor as new (path: string) => unknown)(filePath) as T;\n } catch (cause) {\n betterSqliteCause = cause;\n }\n // Fallback: the Node 22.5+ built-in driver (the path the error message documents).\n // `process.getBuiltinModule` (Node 22.3+) instead of `import(\"node:sqlite\")` — bundlers that\n // predate the sqlite builtin rewrite the import specifier to a bare \"sqlite\" package (proven in\n // the published dist: \"Cannot find package 'sqlite'\"), while getBuiltinModule is opaque to them.\n try {\n const mod = (await (driverLoaderOverrides?.nodeSqlite?.() ??\n Promise.resolve(\n (process as { getBuiltinModule?: (id: string) => unknown }).getBuiltinModule?.(\n \"node:sqlite\",\n ) ??\n (() => {\n throw new Error(\"node:sqlite built-in unavailable (Node < 22.3)\");\n })(),\n ))) as {\n DatabaseSync: new (\n path: string,\n ) => {\n prepare(sql: string): unknown;\n exec(sql: string): void;\n close(): void;\n };\n };\n return adaptNodeSqlite(new mod.DatabaseSync(filePath)) as T;\n } catch (nodeSqliteCause) {\n const b =\n betterSqliteCause instanceof Error ? betterSqliteCause.message : String(betterSqliteCause);\n const n = nodeSqliteCause instanceof Error ? nodeSqliteCause.message : String(nodeSqliteCause);\n throw new ConfigurationError(\n `Failed to load SQLite driver. Install \\`better-sqlite3\\` or run on Node 22.5+ for built-in \\`node:sqlite\\`. better-sqlite3: ${b}; node:sqlite: ${n}`,\n { code: \"sqlite_driver_unavailable\", cause: nodeSqliteCause },\n );\n }\n}\n\n/** True when an open error indicates an unreadable / corrupt database file. */\nexport function isCorruptionError(cause: unknown): boolean {\n if (!(cause instanceof Error)) return false;\n const msg = cause.message.toLowerCase();\n return (\n msg.includes(\"malformed\") ||\n msg.includes(\"not a database\") ||\n msg.includes(\"encrypted\") ||\n msg.includes(\"disk image is malformed\")\n );\n}\n\nasync function renameAside(filePath: string, label: string): Promise<void> {\n const asidePath = `${filePath}.corrupt-${Date.now()}`;\n await rename(filePath, asidePath).catch(() => undefined);\n await rename(`${filePath}-wal`, `${asidePath}-wal`).catch(() => undefined);\n await rename(`${filePath}-shm`, `${asidePath}-shm`).catch(() => undefined);\n diag(\n `[theokit-sdk] ${label} database corrupt; renamed aside to ${asidePath} and rebuilt schema\\n`,\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/internal/runtime/plugin-loader/plugin-bundles.ts","../src/internal/runtime/skills/subagents-loader.ts"],"names":["pluginBundleRoots","readdir","join","projectConfigRoots","ConfigurationError","diag","readWorkspaceDir","path","readFile","parseSimpleYaml"],"mappings":"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","file":"chunk-AUH2EVWY.cjs","sourcesContent":["/**\n * Locating the plugin bundles a project carries.\n *\n * Shared by the skills and subagents loaders, which both need the same answer to \"which folders in\n * this project are plugins\" and would otherwise each grow their own copy of the directory walk.\n *\n * @internal\n */\n\nimport type { Dirent } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { pluginBundleRoots } from \"../../persistence/paths.js\";\nimport type { CompatSourceDeclaration } from \"../compat/foreign-config-sources.js\";\n\n/**\n * Every plugin folder under the project's plugin roots.\n *\n * Returns the FOLDERS, not their contents — what a bundle contributes (`skills/`, `agents/`) is the\n * caller's business, and a loader that also knew the layout would have to change whenever the other\n * one did.\n *\n * A missing root is not an error: most projects carry no plugins, and treating their absence as a\n * failure would make \"none installed\" indistinguishable from \"the directory could not be read\".\n */\nexport async function pluginBundleDirs(\n cwd: string,\n /** Declared foreign dialects (#524). Empty reads `.theokit/plugins` only. */\n compatSources: readonly CompatSourceDeclaration[] = [],\n): Promise<string[]> {\n const dirs: string[] = [];\n for (const root of pluginBundleRoots(cwd, compatSources)) {\n let entries: Dirent[];\n try {\n entries = await readdir(root, { withFileTypes: true });\n } catch {\n continue;\n }\n for (const entry of entries) {\n if (entry.isDirectory()) dirs.push(join(root, entry.name));\n }\n }\n return dirs;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { ConfigurationError } from \"../../../errors.js\";\nimport type { AgentDefinition } from \"../../../types/agent.js\";\nimport type { ModelSelection } from \"../../../types/agent-prims.js\";\nimport { diag } from \"../../diagnostics.js\";\nimport { projectConfigRoots } from \"../../persistence/paths.js\";\nimport type { CompatSourceDeclaration } from \"../compat/foreign-config-sources.js\";\nimport { readWorkspaceDir } from \"../config/workspace-dir.js\";\nimport { type FrontmatterValue, parseSimpleYaml } from \"../context/yaml-frontmatter.js\";\nimport { pluginBundleDirs } from \"../plugin-loader/plugin-bundles.js\";\n\n/**\n * Load file-based subagents from `.theokit/agents/*.md` and merge with\n * inline definitions. Inline overrides file-based on name conflict.\n *\n * Each markdown file has YAML frontmatter (description + optional model)\n * and a body that becomes the subagent prompt.\n *\n * @internal\n */\nexport async function loadSubagents(\n cwd: string,\n settingSourcesIncludeProject: boolean,\n inline: Record<string, AgentDefinition> | undefined,\n /** Declared foreign dialects (#524). Empty reads `.theokit/` only. */\n compatSources: readonly CompatSourceDeclaration[] = [],\n): Promise<Record<string, AgentDefinition>> {\n const result: Record<string, AgentDefinition> = {};\n if (settingSourcesIncludeProject) {\n const projectAgents = await readProjectSubagents(cwd, compatSources);\n for (const [name, definition] of Object.entries(projectAgents)) {\n result[name] = definition;\n }\n }\n if (inline !== undefined) {\n for (const [name, definition] of Object.entries(inline)) {\n result[name] = definition;\n }\n }\n return result;\n}\n\n/**\n * Read agent declarations from every project config root (`.theokit`, then `.claude`).\n *\n * FIRST occurrence of a name wins, which is what makes `projectConfigRoots`' order a contract rather\n * than a detail: a project declaring the same agent in both means the explicit namespace.\n */\nasync function readProjectSubagents(\n cwd: string,\n compatSources: readonly CompatSourceDeclaration[],\n): Promise<Record<string, AgentDefinition>> {\n const subagents: Record<string, AgentDefinition> = {};\n for (const configRoot of projectConfigRoots(cwd, compatSources, \"subagents\")) {\n await readSubagentsFrom(join(configRoot, \"agents\"), subagents);\n }\n // A Claude Code plugin is a BUNDLE, and its `agents/` is what it exists to contribute. Read after\n // the project's own, so a project can shadow an agent a plugin ships without editing the plugin.\n for (const bundle of await pluginBundleDirs(cwd, compatSources)) {\n await readSubagentsFrom(join(bundle, \"agents\"), subagents);\n }\n return subagents;\n}\n\n/**\n * Parse an agent file, or return null when it was written for another runtime.\n *\n * ## What this changed, and what it deliberately did not\n *\n * The failure used to take the whole directory, and that was a decision rather than an oversight:\n * \"a file that HAS frontmatter and gets it wrong is a broken agent and still fails loudly, which is\n * what keeps a typo'd `sandbox` from returning as a silent gate through this door. Isolating the\n * failure per file would hand that risk back.\"\n *\n * The risk named there is real and is NOT handed back, because the isolation is narrower than the\n * one that argument refuses. Only `KNOWN_CLAUDE_CODE_FIELDS` takes this door — the set that already\n * encodes \"this key belongs to another runtime and carries no behaviour here\". A misspelling of one\n * of OUR keys carries `subagent_unknown_field` and still propagates, so `sandboxx` remains fatal\n * and cannot return as a silent gate. `a-claude-code-field-names-itself.test.ts` pins both halves.\n *\n * What moved the decision was the cost, measured in a live TUI on 2026-09-15: one ported\n * `.claude/agents/*.md` carrying `memory:` stopped every sibling agent from loading and the turn\n * produced no answer at all — on an agent the task never used. Beside it, on the same prompt and\n * the same project, another runtime answered normally. The diagnosis fix this file shipped tells a\n * user which key is foreign; it does not give them back the turn.\n *\n * The loader already draws exactly this line for a file with no frontmatter, and for the same\n * stated reason: one of them must not stop every agent in the directory from loading.\n */\nfunction parseOrSkipForeignRuntime(\n raw: string,\n filename: string,\n): { name: string; definition: AgentDefinition } | null {\n try {\n return parseSubagentMarkdown(raw, filename);\n } catch (error) {\n if (error instanceof ConfigurationError && error.code === \"subagent_foreign_runtime_field\") {\n diag(`[theokit-sdk] ${filename}: ${error.message} — skipping this agent`);\n return null;\n }\n throw error;\n }\n}\n\nasync function readSubagentsFrom(\n root: string,\n subagents: Record<string, AgentDefinition>,\n): Promise<void> {\n const entries = await readWorkspaceDir(root, \"subagents_read_error\", \"subagents directory\");\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith(\".md\")) continue;\n const path = join(root, entry.name);\n const raw = await readFile(path, \"utf8\");\n // A markdown file with NO frontmatter is not an agent declaration — a directory of agents\n // written for the Claude Code CLI conventionally carries documentation beside them, and\n // `.claude/agents/README.md` exists in this repository. Throwing on it made ONE such file stop\n // every agent in the directory from loading.\n //\n // Skipped with a warn rather than in silence, and ONLY for the no-frontmatter case: a file that\n // HAS frontmatter and gets it wrong is a broken agent and still fails loudly, which is what\n // keeps a typo'd `sandbox` from returning as a silent gate through this door.\n if (!hasFrontmatter(raw)) {\n diag(`[theokit-sdk] ${entry.name} has no frontmatter — not an agent declaration, skipping`);\n continue;\n }\n const definition = parseOrSkipForeignRuntime(raw, entry.name);\n if (definition === null) continue;\n if (subagents[definition.name] === undefined) {\n // `path` is computed above to read the file and was then dropped. Keeping it is the whole\n // visibility fix (#524): without it a listing cannot say which root an agent came from.\n subagents[definition.name] = { ...definition.definition, source: path };\n }\n }\n}\n\n// The frontmatter keys a disk subagent may declare. Any other key is a typed load\n// error rather than a silent drop — a dropped `sandbox` an operator wrote believing\n// it confines the child is exactly the silent-gate failure class this guards against.\nconst ACCEPTED_FIELDS = new Set([\n \"name\",\n \"description\",\n \"model\",\n \"tools\",\n \"reasoning_effort\",\n \"mcp\",\n \"sandbox\",\n \"memory\",\n]);\n\n// Fields the Claude Code CLI writes that carry NO behaviour for this runtime. Accepted and ignored,\n// so an agent authored for the CLI loads here unchanged — measured 2026-08-26 across the 59 agent\n// files on one machine, where `color` appeared in 38 of them and made every one of those a\n// `subagent_unknown_field` load error.\n//\n// Named explicitly instead of loosening the check above, because that check's reason is sound: a\n// dropped `sandbox` an operator wrote believing it confines the child is a silent gate. A field that\n// COULD change behaviour must still fail loudly. This set is the difference between \"we know this\n// one and it does nothing\" and \"we have never heard of this\" — two facts a bare allow-everything\n// would collapse into one.\n//\n// Anything added here needs the same justification: inert for THIS runtime, not merely unfamiliar.\nconst INERT_CLAUDE_CODE_FIELDS = new Set([\n /** The CLI's label colour for the agent. Presentation only. */\n \"color\",\n]);\n\nfunction parseSubagentMarkdown(\n raw: string,\n filename: string,\n): { name: string; definition: AgentDefinition } {\n const { frontmatter, body } = splitFrontmatter(raw, filename);\n const fields = parseFrontmatterFields(frontmatter);\n rejectUnknownFields(fields, filename);\n rejectMcp(fields, filename);\n\n const definition: AgentDefinition = {\n description: asString(fields.description) ?? \"\",\n prompt: body,\n };\n const model = resolveModel(fields, filename);\n if (model !== undefined) definition.model = model;\n const tools = toStringList(fields.tools);\n if (tools.length > 0) definition.tools = tools;\n const sandbox = resolveSandbox(fields, filename);\n if (sandbox !== undefined) definition.sandbox = sandbox;\n // Carried unjudged — see `AgentDefinition.memory`. Which root a scope names, and whether the\n // name is one at all, is `@theokit/agents`' decision and refusing it twice means two lists.\n const memory = asString(fields.memory);\n if (memory !== undefined) definition.memory = memory;\n\n const name = asString(fields.name) ?? filename.replace(/\\.md$/, \"\");\n return { name, definition };\n}\n\n/**\n * Frontmatter keys that Claude Code documents for a subagent and this runtime does not accept.\n *\n * Not an allow-list — every one of these still fails the load. It exists so the FAILURE can say\n * which kind of unknown it met. A user migrating a `.claude/agents/` tree used to learn one key per\n * round trip: fix `memory`, meet `permissionMode`, fix that, meet `maxTurns` — with nothing saying\n * the set was finite or that the tree was simply written for another runtime.\n *\n * The distinction this file already draws for `INERT_CLAUDE_CODE_FIELDS` is the same one: \"the\n * difference between 'we know this one and it does nothing' and 'we have never heard of this' — two\n * facts a bare allow-everything would collapse into one.\" This is the third fact beside them —\n * \"another runtime's field\" — and it changes only the message, never the verdict.\n */\nconst KNOWN_CLAUDE_CODE_FIELDS = new Set([\n \"disallowedTools\",\n \"permissionMode\",\n \"maxTurns\",\n \"skills\",\n \"background\",\n \"effort\",\n \"isolation\",\n \"initialPrompt\",\n \"hooks\",\n \"experimental\",\n \"mcpServers\",\n]);\n\n/**\n * The typed error for a key we do not accept. Built here rather than inline so `rejectUnknownFields`\n * stays a plain loop: the message has two shapes and the code has two values, and computing all four\n * at the throw site is what pushed that function past the cognitive-complexity gate.\n */\nfunction unknownFieldError(key: string, filename: string): ConfigurationError {\n const foreign = KNOWN_CLAUDE_CODE_FIELDS.has(key);\n const siblings = [...KNOWN_CLAUDE_CODE_FIELDS].filter((f) => f !== key);\n const origin = foreign\n ? ` — \"${key}\" is a Claude Code subagent field that this runtime does not support. ` +\n `The same applies to: ${siblings.join(\", \")}. Removing them one at a time will meet each ` +\n `in turn; the tree is written for another runtime`\n : \"\";\n // The two codes are written as LITERALS, one per branch, rather than as a ternary inside the\n // options object. `tools/generate-error-codes.mjs` walks the source for the literal assigned to\n // `code:`, so a ternary there is not a literal and it extracted NEITHER — measured 2026-09-15,\n // when `quality:docs-errors` went red and the regenerated reference had lost\n // `subagent_unknown_field` without ever gaining `subagent_foreign_runtime_field`. Two real,\n // throwable codes were absent from the published error reference, which is the one place a\n // consumer looks to find out what they can catch.\n if (foreign)\n return new ConfigurationError(\n `Subagent ${filename}: unknown frontmatter field \"${key}\" (accepted: ${[...ACCEPTED_FIELDS].join(\", \")})${origin}`,\n { code: \"subagent_foreign_runtime_field\" },\n );\n return new ConfigurationError(\n `Subagent ${filename}: unknown frontmatter field \"${key}\" (accepted: ${[...ACCEPTED_FIELDS].join(\", \")})${origin}`,\n { code: \"subagent_unknown_field\" },\n );\n}\n\nfunction rejectUnknownFields(\n fields: Record<string, FrontmatterValue | undefined>,\n filename: string,\n): void {\n for (const key of Object.keys(fields)) {\n if (INERT_CLAUDE_CODE_FIELDS.has(key)) continue;\n if (!ACCEPTED_FIELDS.has(key)) throw unknownFieldError(key, filename);\n }\n}\n\n// mcp: a known field, but not yet honored on the LOCAL delegation path. The frontmatter YAML can only\n// express server NAMES (parseSimpleYaml has no nested-object support), while a child's `Agent.create`\n// needs `mcpServers` as a Record<name, config>; resolving names→config per-subagent in local delegation\n// is its own follow-up. Rather than silently drop it (the M26/M32 silent-gate class), it is a typed load\n// error that names the field and points at the alternative.\nfunction rejectMcp(fields: Record<string, FrontmatterValue | undefined>, filename: string): void {\n if (fields.mcp !== undefined) {\n throw new ConfigurationError(\n `Subagent ${filename}: per-subagent \"mcp\" is not yet supported on the local delegation path; declare MCP servers in .theokit/mcp.json (or the parent) instead`,\n { code: \"subagent_mcp_unsupported_local\" },\n );\n }\n}\n\n// model + reasoning_effort — effort rides inside `model.params[thinking]`, so it requires a concrete\n// model id to attach to (a child inheriting the parent's model cannot carry the parent's provider-\n// specific effort param safely).\nfunction resolveModel(\n fields: Record<string, FrontmatterValue | undefined>,\n filename: string,\n): ModelSelection | \"inherit\" | undefined {\n const modelId = asString(fields.model);\n // An empty/blank effort (`reasoning_effort: \"\"`) names nothing: treated as absent, never as a\n // `{ id: \"thinking\", value: \"\" }` param the provider would drop or reject.\n const rawEffort = asString(fields.reasoning_effort)?.trim();\n const effort = rawEffort === \"\" ? undefined : rawEffort;\n // reasoning_effort rides in model.params[thinking], so it needs a CONCRETE model id to attach to.\n // Neither an absent model NOR `model: inherit` can carry it (the inherited id is unknown at load), so\n // both are typed errors rather than a silently-dropped effort — the silent-gate class this guards.\n if (effort !== undefined && (modelId === undefined || modelId === \"inherit\")) {\n throw new ConfigurationError(\n `Subagent ${filename}: reasoning_effort requires a concrete model (effort is a model parameter; an absent model or \"inherit\" cannot carry it)`,\n { code: \"subagent_reasoning_effort_without_model\" },\n );\n }\n if (modelId === undefined) return undefined;\n if (modelId === \"inherit\") return \"inherit\";\n return effort !== undefined\n ? { id: modelId, params: [{ id: \"thinking\", value: effort }] }\n : { id: modelId };\n}\n\n// sandbox: boolean only. A granular mode string (read-only/…) is unsupported by the SDK runtime and is\n// a typed error rather than a silent coercion to a boolean.\nfunction resolveSandbox(\n fields: Record<string, FrontmatterValue | undefined>,\n filename: string,\n): boolean | undefined {\n if (fields.sandbox === undefined) return undefined;\n if (typeof fields.sandbox !== \"boolean\") {\n throw new ConfigurationError(\n `Subagent ${filename}: sandbox must be a boolean (got \"${String(fields.sandbox)}\"); granular sandbox modes are not supported by the runtime`,\n { code: \"subagent_sandbox_not_boolean\" },\n );\n }\n return fields.sandbox;\n}\n\nfunction asString(v: FrontmatterValue | undefined): string | undefined {\n if (typeof v !== \"string\") return undefined;\n // parseSimpleYaml does not strip quotes (documented), and `model`/`reasoning_effort` are fields users\n // habitually quote (`model: \"openai/gpt-4o\"`). Strip a single matching surrounding quote pair so a\n // quoted id/effort does not slip past validation and fail only at the provider.\n const m = /^([\"'])(.*)\\1$/.exec(v);\n return m ? m[2] : v;\n}\n\n/** Accept a YAML list (`string[]`) or a comma/space-separated scalar; trim + drop empties. */\nfunction toStringList(v: FrontmatterValue | undefined): string[] {\n if (Array.isArray(v)) return v.map((t) => t.trim()).filter((t) => t.length > 0);\n if (typeof v === \"string\") {\n return v\n .split(/[\\s,]+/)\n .map((t) => t.trim())\n .filter((t) => t.length > 0);\n }\n return [];\n}\n\n/** Does this file open with a frontmatter block at all? Its ABSENCE means \"not an agent\". */\nfunction hasFrontmatter(raw: string): boolean {\n return /^---\\s*\\n/.test(raw);\n}\n\nfunction splitFrontmatter(raw: string, filename: string): { frontmatter: string; body: string } {\n const match = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n([\\s\\S]*)$/.exec(raw);\n if (match === null) {\n throw new ConfigurationError(`Subagent ${filename} is missing frontmatter`, {\n code: \"subagent_missing_frontmatter\",\n });\n }\n return { frontmatter: match[1] ?? \"\", body: (match[2] ?? \"\").trim() };\n}\n\nfunction parseFrontmatterFields(frontmatter: string): Record<string, FrontmatterValue | undefined> {\n // Preserve the rich YAML value types (boolean/number/string[]): `sandbox: true` and\n // `mcp: [a, b]` are meaningful here, so narrowing everything to string (as the\n // pre-M33 loader did) would drop them. Per-field validation happens in parseSubagentMarkdown.\n return parseSimpleYaml(frontmatter);\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/internal/task/task-id.ts","../src/internal/task/store.ts"],"names":["InvalidTaskIdError","mkdirSync","join","atomicWriteText","readFile","diag","readdirSync","unlink"],"mappings":"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","file":"chunk-BWYC7RZG.cjs","sourcesContent":["/**\n * Task-id grammar (D368) — runtime, deliberately NOT in `types/`.\n *\n * It lived in `types/task.ts`, which `types/index.ts` re-exports with `export type *`. That star\n * cannot carry a value, so the only reason `isValidTaskId` ever reached a consumer is that the DTS\n * rollup hoists the declaration while the runtime bundle emits nothing — exactly the shape of #279,\n * where the import typechecked and was `undefined` at the call site. `src/index.ts` re-exports both\n * names from here, so the public API is unchanged.\n *\n * @internal\n */\n\n/**\n * Grammar for user-supplied task IDs (D368).\n * `crypto.randomUUID()` outputs do NOT match this (UUIDs have dashes\n * AND uppercase letters in their canonical form on some Node versions),\n * but the registry normalizes auto-generated IDs to lowercase before\n * insertion, so they pass the same regex.\n */\nconst TASK_ID_GRAMMAR = /^[a-z0-9][a-z0-9_-]*$/;\n\n/** Reserved prefixes for adapter-generated IDs (D368, EC-5). */\nconst RESERVED_PREFIXES = [\"wf-\", \"b-\", \"cron-\"] as const;\n\n/**\n * Validates a task ID against the public grammar + reserved prefixes.\n * Throws `InvalidTaskIdError` from `../errors.js` on rejection.\n *\n * Adapter callers (workflow/batch/cron) MUST set `allowReserved: true`\n * to register their own IDs; user-facing surfaces (`Task.submit`,\n * `agent.send({ task: { id } })`) leave it false.\n */\nexport function isValidTaskId(id: string, allowReserved: boolean): boolean {\n if (!TASK_ID_GRAMMAR.test(id)) return false;\n if (allowReserved) return true;\n for (const prefix of RESERVED_PREFIXES) {\n if (id.startsWith(prefix)) return false;\n }\n return true;\n}\n\n/** Re-exported for adapter implementations + tests. */\nexport const TASK_RESERVED_PREFIXES: readonly string[] = RESERVED_PREFIXES;\n","/**\n * `TaskStore` interface + 2 implementations (ADR D364).\n *\n * - `InMemoryTaskStore` — default, transient, single-process.\n * - `JsonFileTaskStore` — opt-in, one JSON file per task under a\n * dedicated dir; single-process invariant (EC-15 documented).\n *\n * Edge cases absorbed:\n * - EC-1: constructor auto-creates dir (mkdirSync recursive idempotent).\n * - EC-2: every method validates the task id against the public\n * grammar (D368) BEFORE doing any path I/O — path-traversal defense.\n * - EC-6: `list()` returns `[]` on ENOENT (fresh install path).\n * - EC-8: `list()` skips `.tmp.*` orphan files left by interrupted\n * atomic writes.\n * - EC-14 (DOCUMENT): `list()` JSDoc documents the 256-row hard cap.\n * It no longer advertises `submittedBefore` as a way to page past it:\n * the cap is applied to the raw directory listing before any filter, so\n * paging beyond 256 files is not reachable through this interface.\n * - EC-15 (DOCUMENT): `JsonFileTaskStore` JSDoc documents the\n * single-process invariant; v0.2 SQLite covers cross-process.\n *\n * @internal\n */\n\nimport { mkdirSync, readdirSync } from \"node:fs\";\nimport { readFile, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { InvalidTaskIdError } from \"../../errors.js\";\nimport type { TaskFilter, TaskHandle, TaskState, TaskStoreOptions } from \"../../types/task.js\";\nimport { diag } from \"../diagnostics.js\";\nimport { atomicWriteText } from \"../persistence/atomic-write.js\";\nimport { isValidTaskId } from \"./task-id.js\";\n\nconst JSON_LOAD_CAP = 256;\nconst DEFAULT_LIST_LIMIT = 100;\n\n/** Storage interface used by `TaskRegistry`. */\nexport interface TaskStore {\n insert(handle: TaskHandle): Promise<void>;\n update(id: string, mutate: (h: TaskHandle) => TaskHandle): Promise<TaskHandle | undefined>;\n get(id: string): Promise<TaskHandle | undefined>;\n /**\n * Returns at most `filter.limit ?? 100` matching handles.\n *\n * `JsonFileTaskStore` returns them newest-first and considers every task in its\n * directory, reading at most 256 files concurrently (#362 — that number bounds\n * I/O, not which tasks are visible). Walk past `limit` by passing the oldest\n * `submittedAt` of a page as the next call's `submittedBefore`; the ordering is\n * what makes that a cursor rather than a re-roll of an arbitrary subset.\n * `InMemoryTaskStore` applies the same filters but does not order its result.\n */\n list(filter: TaskFilter): Promise<TaskHandle[]>;\n delete(id: string): Promise<boolean>;\n /** Removes terminal handles whose terminal-timestamp is older than `epochMs`. */\n evictTerminalOlderThan(epochMs: number): Promise<number>;\n}\n\nfunction assertValidIdForStore(id: string): void {\n if (!isValidTaskId(id, /* allowReserved */ true)) {\n throw new InvalidTaskIdError(`store rejects invalid task id: ${id}`, id);\n }\n}\n\nfunction terminalTimestamp(h: TaskHandle): number | undefined {\n if (h.state === \"finished\") return h.finishedAt;\n if (h.state === \"error\") return h.erroredAt;\n if (h.state === \"cancelled\") return h.cancelledAt;\n return undefined;\n}\n\nfunction isTerminal(state: TaskState): boolean {\n return state === \"finished\" || state === \"error\" || state === \"cancelled\";\n}\n\nfunction matchesState(h: TaskHandle, filter: TaskFilter): boolean {\n if (filter.state === undefined) return true;\n const states = Array.isArray(filter.state) ? filter.state : [filter.state];\n return states.includes(h.state);\n}\nfunction matchesKind(h: TaskHandle, filter: TaskFilter): boolean {\n if (filter.kind === undefined) return true;\n const kinds = Array.isArray(filter.kind) ? filter.kind : [filter.kind];\n return kinds.includes(h.kind);\n}\nfunction matchesTime(h: TaskHandle, filter: TaskFilter): boolean {\n if (filter.submittedAfter !== undefined && h.submittedAt <= filter.submittedAfter) return false;\n if (filter.submittedBefore !== undefined && h.submittedAt >= filter.submittedBefore) return false;\n return true;\n}\nfunction matchesFilter(h: TaskHandle, filter: TaskFilter): boolean {\n return matchesState(h, filter) && matchesKind(h, filter) && matchesTime(h, filter);\n}\n\n/** The states `evictTerminalOlderThan` considers terminal. */\nconst TERMINAL_STATES: readonly TaskState[] = [\"finished\", \"error\", \"cancelled\"];\n\n/**\n * Where `submittedAt` belongs in a newest-first list — the first index whose entry is older.\n *\n * Linear rather than binary: the list is bounded by the caller's `limit` (100 by default) and the\n * scan runs once per MATCHING handle, so the comparison count is dwarfed by the file read that\n * produced the handle. A binary search here would trade a real cost for an imagined one.\n */\nfunction insertionIndex(newestFirst: readonly TaskHandle[], submittedAt: number): number {\n for (let i = 0; i < newestFirst.length; i++) {\n const entry = newestFirst[i];\n if (entry !== undefined && entry.submittedAt < submittedAt) return i;\n }\n return newestFirst.length;\n}\n\nfunction applyFilter(values: Iterable<TaskHandle>, filter: TaskFilter): TaskHandle[] {\n const limit = filter.limit ?? DEFAULT_LIST_LIMIT;\n const out: TaskHandle[] = [];\n for (const h of values) {\n if (matchesFilter(h, filter)) {\n out.push(h);\n if (out.length >= limit) break;\n }\n }\n return out;\n}\n\n/* ─── InMemory ─── */\n\n/**\n * Default `TaskStore` — a plain `Map` living in the current process.\n *\n * Nothing reaches disk and nothing survives the process, so a task recorded here\n * is invisible to a reader in another process (`theokit tasks`). Select it with\n * `getTaskStoreFor({ backend: \"memory\" })`.\n *\n * How it fails: every id-taking method validates against the task-id grammar\n * (`^[a-z0-9][a-z0-9_-]*$`; reserved `wf-`/`b-`/`cron-` prefixes are permitted\n * here) and throws `InvalidTaskIdError` before touching the map. A missing id is\n * reported by returning `undefined` (`get`, `update`) or `false` (`delete`), never\n * by throwing.\n *\n * Traps:\n * - `insert()` is a `Map.set`: an existing id is overwritten silently, not\n * rejected.\n * - `list()` walks in INSERTION order and stops as soon as `filter.limit ?? 100`\n * matches are collected. It never sorts, so the limit truncates an\n * oldest-first scan rather than returning the most recent tasks.\n * - Nothing evicts on its own; terminal handles accumulate until a caller invokes\n * `evictTerminalOlderThan`.\n */\nexport class InMemoryTaskStore implements TaskStore {\n private readonly map = new Map<string, TaskHandle>();\n\n async insert(handle: TaskHandle): Promise<void> {\n assertValidIdForStore(handle.id);\n this.map.set(handle.id, handle);\n }\n\n async update(id: string, mutate: (h: TaskHandle) => TaskHandle): Promise<TaskHandle | undefined> {\n assertValidIdForStore(id);\n const existing = this.map.get(id);\n if (existing === undefined) return undefined;\n const next = mutate(existing);\n this.map.set(id, next);\n return next;\n }\n\n async get(id: string): Promise<TaskHandle | undefined> {\n assertValidIdForStore(id);\n return this.map.get(id);\n }\n\n async list(filter: TaskFilter): Promise<TaskHandle[]> {\n return applyFilter(this.map.values(), filter);\n }\n\n async delete(id: string): Promise<boolean> {\n assertValidIdForStore(id);\n return this.map.delete(id);\n }\n\n async evictTerminalOlderThan(epochMs: number): Promise<number> {\n let count = 0;\n for (const [id, h] of this.map.entries()) {\n if (!isTerminal(h.state)) continue;\n const ts = terminalTimestamp(h);\n if (ts !== undefined && ts < epochMs) {\n this.map.delete(id);\n count++;\n }\n }\n return count;\n }\n}\n\n/* ─── JsonFile (opt-in) ───\n *\n * IMPORTANT (EC-15): `JsonFileTaskStore` is **single-process**.\n * Concurrent writers from multiple Node processes against the same\n * directory may corrupt entries (atomic-write protects per-file, but\n * the `list()` scan + `update()` read-modify-write cycle is not\n * serialised across processes). Use only when the `TaskRegistry`\n * runs in exactly one process. v0.2 will add a SQLite backend with\n * the same interface for cross-process scenarios (D364 + D61).\n */\n/**\n * Opt-in `TaskStore` that keeps one JSON file per task under `dir`, so another\n * process can read the registry off disk.\n *\n * const store = new JsonFileTaskStore(\"/var/lib/theokit/tasks\");\n *\n * Two calls are synchronous, and both are deliberate: the constructor creates `dir`\n * recursively (`mkdirSync`), and `list()` scans it with `readdirSync` before awaiting\n * anything. Every other operation is async — `get` uses `readFile`, `delete` uses\n * `unlink`, and every write goes through an atomic temp-file-plus-rename.\n *\n * SINGLE-PROCESS ONLY — see the note above. Per-file atomicity does not make\n * `update()` safe: it is a read-modify-write, so two writers that both `get`\n * before either writes lose one of the two mutations. That is true within one\n * process as well as across processes.\n *\n * How it fails:\n * - An invalid id throws `InvalidTaskIdError` BEFORE any path is constructed.\n * That ordering is the path-traversal defence, and it is why ids are validated\n * rather than escaped.\n * - A missing task is `undefined` from `get` and `false` from `delete`.\n * - A file that exists but does not parse is NOT surfaced as an error: `get`\n * writes to the diagnostics channel and returns `undefined`, so a corrupted\n * task also silently vanishes from `list()`.\n * - `list()` returns `[]` when `dir` does not exist; any other `readdir` failure\n * (for example a permission error) throws.\n *\n * Traps:\n * - `list()` reads every task file in the directory (256 at a time) to apply the\n * filter, because `state`, `kind` and `submittedAt` live inside the files. On a\n * large directory that is a lot of I/O for one call; the memory it holds is\n * bounded by `limit`, the time is not.\n * - `list()` is `async`, but its directory scan is not: `readdirSync` blocks the event\n * loop for the whole listing before the first `await`. Only the per-file reads that\n * follow it are concurrent.\n * - Files whose name contains `.tmp` are skipped as orphans of an interrupted\n * write, and nothing ever removes them.\n */\nexport class JsonFileTaskStore implements TaskStore {\n constructor(private readonly dir: string) {\n // EC-1: idempotent mkdir; ignore EEXIST.\n try {\n mkdirSync(dir, { recursive: true });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"EEXIST\") throw err;\n }\n }\n\n private filePath(id: string): string {\n return join(this.dir, `${id}.json`);\n }\n\n async insert(handle: TaskHandle): Promise<void> {\n assertValidIdForStore(handle.id);\n await atomicWriteText(this.filePath(handle.id), JSON.stringify(handle));\n }\n\n async update(id: string, mutate: (h: TaskHandle) => TaskHandle): Promise<TaskHandle | undefined> {\n assertValidIdForStore(id);\n const existing = await this.get(id);\n if (existing === undefined) return undefined;\n const next = mutate(existing);\n await atomicWriteText(this.filePath(id), JSON.stringify(next));\n return next;\n }\n\n async get(id: string): Promise<TaskHandle | undefined> {\n assertValidIdForStore(id);\n try {\n const raw = await readFile(this.filePath(id), \"utf8\");\n return JSON.parse(raw) as TaskHandle;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") return undefined;\n // Corrupt JSON or other I/O error — log + degrade gracefully (D50/EC-7 cache pattern).\n diag(`[task-store] failed to read ${id}: ${(err as Error).message}\\n`);\n return undefined;\n }\n }\n\n /**\n * Task ids backed by a file in `dir`, in readdir order.\n *\n * EC-8: orphan `.tmp` files left by an interrupted atomic write are skipped, as is any name\n * outside the id grammar. EC-6: a missing directory lists as empty; any other `readdir` failure\n * (a permission error, say) throws rather than being reported as \"no tasks\".\n */\n private candidateIds(): string[] {\n let entries: string[];\n try {\n entries = readdirSync(this.dir);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return []; // EC-6\n throw err;\n }\n return entries\n .filter((name) => name.endsWith(\".json\") && !name.includes(\".tmp\"))\n .map((name) => name.slice(0, -\".json\".length))\n .filter((id) => isValidTaskId(id, true));\n }\n\n /**\n * Read every task in `ids`, handing each loaded handle to `visit`, at most `JSON_LOAD_CAP` file\n * reads in flight.\n *\n * #362 — the cap used to be applied to the directory listing, which made it a bound on WHICH\n * tasks were visible rather than on how much I/O ran at once. Every filter then ran on that\n * arbitrary readdir-ordered prefix. As a concurrency bound it does the job it was named for\n * without deciding what the caller gets to see; the caller's own bound on memory is whatever\n * `visit` chooses to retain.\n */\n private async forEachHandle(\n ids: readonly string[],\n visit: (handle: TaskHandle) => void | Promise<void>,\n ): Promise<void> {\n for (let start = 0; start < ids.length; start += JSON_LOAD_CAP) {\n const batch = ids.slice(start, start + JSON_LOAD_CAP);\n const loaded = await Promise.all(batch.map(async (id) => this.get(id)));\n for (const handle of loaded) {\n if (handle !== undefined) await visit(handle);\n }\n }\n }\n\n async list(filter: TaskFilter): Promise<TaskHandle[]> {\n const limit = filter.limit ?? DEFAULT_LIST_LIMIT;\n // Newest-first, keeping at most `limit` handles in memory regardless of how many match. The\n // order is what makes `submittedBefore` a real cursor: with the previous readdir order, a page\n // was an arbitrary subset, so a caller walking the timeline skipped every task that happened\n // to fall outside its window and could never come back for them.\n const newest: TaskHandle[] = [];\n await this.forEachHandle(this.candidateIds(), (handle) => {\n if (!matchesFilter(handle, filter)) return;\n const at = insertionIndex(newest, handle.submittedAt);\n if (at >= limit) return; // older than everything already held, and the page is full\n newest.splice(at, 0, handle);\n if (newest.length > limit) newest.pop();\n });\n return newest;\n }\n\n async delete(id: string): Promise<boolean> {\n assertValidIdForStore(id);\n try {\n await unlink(this.filePath(id));\n return true;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n throw err;\n }\n }\n\n async evictTerminalOlderThan(epochMs: number): Promise<number> {\n // #362 — eviction scans the directory itself rather than borrowing `list()`. Sharing that path\n // made one call incomplete twice over: it saw only a 256-file window, and it wanted the OLDEST\n // handles while `list()` is ordered newest-first — so on a large directory it could delete\n // nothing while thousands of eligible handles sat just outside the page. Sweeping every\n // candidate is what lets one call mean \"everything eligible is gone\".\n let count = 0;\n await this.forEachHandle(this.candidateIds(), async (handle) => {\n if (!TERMINAL_STATES.includes(handle.state)) return;\n const ts = terminalTimestamp(handle);\n if (ts === undefined || ts >= epochMs) return;\n if (await this.delete(handle.id)) count++;\n });\n return count;\n }\n}\n\n/** Factory used by `TaskRegistry.configure` (D364). */\nexport function getTaskStoreFor(options: TaskStoreOptions): TaskStore {\n if (options.backend === \"memory\") return new InMemoryTaskStore();\n return new JsonFileTaskStore(options.dir);\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/internal/memory/dreaming/diary.ts","../src/internal/memory/dreaming/phases.ts","../src/internal/memory/dreaming/run.ts","../src/internal/memory/migrate-sqlite-to-lance.ts"],"names":["join","readFile","replaceFileAtomic","createHash","kept","withCwdMutex","resolveMemoryRoot","readFactsFromMarkdown","diag","mkdir","defaultIndexPath","existsSync","openMemoryDb","ConfigurationError","lanceStoragePath","redactSecrets","rmSync","mkdirSync","LanceIndex","renameSync"],"mappings":"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","file":"chunk-CHKV2L2Y.cjs","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { replaceFileAtomic } from \"../../persistence/atomic-write.js\";\nimport type { MemoryRoot } from \"../storage/memory-root.js\";\n\n/**\n * Dream-diary append (ADR D7).\n *\n * Diary lives at `.theokit/memory/dream-diary.md` and grows with one entry\n * per sweep. Each entry is content-hashed so the same input produces the\n * same entry — idempotency contract.\n *\n * Writes go through `replaceFileAtomic` (EC-3 of edge-case review) so a\n * crash mid-write can never leave a half-written diary.\n *\n * Shared with `@theokit/sdk-memory`; see the memory-store barrel.\n */\n\nexport interface DiaryEntry {\n timestampMs: number;\n factsBefore: number;\n factsAfter: number;\n duplicatesRemoved: number;\n clustersCreated: number;\n notesWritten: number;\n}\n\n/** `<memory root>/dream-diary.md`. Takes the RESOLVED ROOT — see `storage/memory-root.ts` (#463). */\nexport function diaryPath(root: MemoryRoot): string {\n return join(root, \"dream-diary.md\");\n}\n\n/**\n * One diary entry as the markdown that gets appended: a timestamp heading, the short entry hash,\n * and the counts the sweep produced. The hash is what makes a re-run recognisable as the same\n * sweep rather than a new one.\n */\nexport function renderDiaryEntry(entry: DiaryEntry): string {\n const stamp = new Date(entry.timestampMs).toISOString();\n const hash = entryHash(entry).slice(0, 8);\n return [\n `## ${stamp}`,\n \"\",\n `- entry-hash: ${hash}`,\n `- facts before: ${entry.factsBefore}`,\n `- facts after: ${entry.factsAfter}`,\n `- duplicates removed: ${entry.duplicatesRemoved}`,\n `- clusters created: ${entry.clustersCreated}`,\n `- notes written: ${entry.notesWritten}`,\n \"\",\n ].join(\"\\n\");\n}\n\n/**\n * Append one sweep's entry to `<memory root>/dream-diary.md`, creating the file with its header\n * when this is the first sweep. The diary is a human-readable record of what dreaming changed —\n * consolidations are otherwise invisible, because they alter the notes rather than announce\n * themselves.\n */\nexport async function appendDiaryEntry(root: MemoryRoot, entry: DiaryEntry): Promise<void> {\n const path = diaryPath(root);\n let raw = \"\";\n try {\n raw = await readFile(path, \"utf8\");\n } catch {\n raw = \"# Dream Diary\\n\\n\";\n }\n const next = `${raw.endsWith(\"\\n\") ? raw : `${raw}\\n`}${renderDiaryEntry(entry)}`;\n await replaceFileAtomic(path, next);\n}\n\n/**\n * A stable hash of one entry's counts, so two sweeps that did the same work read as the same work.\n * Rendered truncated in the entry; the full value is what callers compare.\n */\nexport function entryHash(entry: DiaryEntry): string {\n return createHash(\"sha256\")\n .update(\n [\n entry.factsBefore,\n entry.factsAfter,\n entry.duplicatesRemoved,\n entry.clustersCreated,\n entry.notesWritten,\n ].join(\"|\"),\n )\n .digest(\"hex\");\n}\n","import type { EmbeddingRuntime } from \"../embedding-adapter.js\";\nimport type { MemoryFact, MemoryKind } from \"../types.js\";\n\n/**\n * Dreaming/REM phase logic.\n *\n * Three phases:\n * - **light** — drop near-duplicate facts (cosine similarity > 0.95).\n * - **REM** — cluster thematically related facts (cosine ≥ 0.75).\n * - **deep** — pick a representative bullet per cluster (longest text\n * wins) and emit consolidated markdown notes.\n */\n\nexport interface DedupResult {\n kept: MemoryFact[];\n duplicatesRemoved: number;\n}\n\n/** A group of semantically similar facts, with the text chosen to represent them. */\nexport interface Cluster {\n representativeText: string;\n members: ReadonlyArray<MemoryFact>;\n}\n\n/** What clustering produced: the clusters and how many facts the per-sweep cap left out. */\nexport interface ClusterResult {\n clusters: Cluster[];\n /** How many input facts past the per-sweep cap were not clustered; 0 when none were. */\n factsLeftOut: number;\n}\n\nconst DEFAULT_DEDUP_THRESHOLD = 0.95;\nconst DEFAULT_CLUSTER_THRESHOLD = 0.75;\n\n/**\n * Kinds a sweep may consolidate. ADR-14 partitions the vocabulary into three buckets and only\n * this one is a merge candidate; the rest are protected for a reason that survives the sweep\n * being non-destructive.\n *\n * `user`, `feedback` and `reference` are ATOMIC: there is nothing to merge and the loss is\n * irreversible. Two corrections a user gave on different days can read alike and are not the\n * same correction. An untyped fact is protected too — a kind that nobody declared is not a\n * licence to treat it as consolidatable.\n *\n * Why this matters even though nothing is deleted: dedup drops the near-duplicate from the\n * CLUSTERING INPUT, and the cluster's representative is what the search index returns. The\n * source file survives; the artefact the agent reads does not. That is ADR-14's third rule —\n * the invariant is about what the agent reads, not what survives on disk.\n */\n// Typed against `MemoryKind` rather than `string`, so the compiler checks these against the vocabulary\n// they mirror. They were `Set<string>` and CONSOLIDATABLE_KINDS held \"session\" — not a member of\n// `MemoryKind`, and rejected by `markdown-store.assertWritable` before any fact is written, so no\n// fact reaching this policy could ever carry it. The arm read as though sessions were consolidatable\n// while no session could exist. Adding a member to either set is now a type error unless `MemoryKind`\n// gains it deliberately.\nconst CONSOLIDATABLE_KINDS: ReadonlySet<MemoryKind> = new Set([\"project\"]);\nconst ATOMIC_KINDS: ReadonlySet<MemoryKind> = new Set([\"user\", \"feedback\", \"reference\"]);\n\n/**\n * Three levels, graded by how much the store knows about the entry. The middle one exists\n * because the first draft of this filter did not have it and broke the common case.\n *\n * - ATOMIC (`user`, `feedback`, `reference`) — never deduplicated. Two corrections given on\n * different days can read alike and are not the same correction.\n * - CONSOLIDATABLE (`project`, `session`) — near-duplicate dedup at the similarity threshold.\n * Overlapping project facts are exactly what a sweep is for.\n * - UNTYPED — EXACT duplicates only. A hand-written bullet under `## Facts` carries no kind,\n * and the store's own header invites editing those by hand, so untyped is the common case\n * rather than an edge one. Treating it as atomic would disable the sweep for most stores;\n * treating it as consolidatable would let a near-duplicate of an untyped correction be\n * dropped. Exact-match is the only claim the store can make without inferring a kind, which\n * is the rule this codebase already applies one field over.\n */\ntype DedupPolicy = \"never\" | \"exact\" | \"similar\";\n\nfunction dedupPolicy(fact: MemoryFact): DedupPolicy {\n if (fact.kind === undefined) return \"exact\";\n if (ATOMIC_KINDS.has(fact.kind)) return \"never\";\n return CONSOLIDATABLE_KINDS.has(fact.kind) ? \"similar\" : \"never\";\n}\n\n/** Whitespace and case collapsed; nothing else. Not a similarity measure — an identity one. */\nfunction normalizeForExactMatch(text: string): string {\n return text\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, \" \")\n .replace(/[.!?]+$/, \"\");\n}\n\n/**\n * Light phase — drop facts whose embedding is too similar to one already kept.\n *\n * Protected kinds bypass deduplication entirely and are returned untouched, so a sweep can\n * never conflate two of them into one representative.\n *\n * \"Drop\" here means DROPPED FROM THE RETURNED LIST. Nothing on disk is deleted, by any phase of\n * this sweep, today.\n *\n * BEFORE YOU ADD PRUNING HERE, READ THIS. The security contract for this store requires a backup\n * to precede any destructive operation (SOP-06-05 step 7). That requirement is currently LATENT\n * — not satisfied, not waived — precisely because the sweep only ever adds notes and filters a\n * list. There is no backup implementation in this package, and an audit that looked for one\n * recorded its absence as having no present consequence.\n *\n * The first commit that makes this sweep delete a file from disk is the commit that makes the\n * gap real, and it is also the commit whose author will have no reason to know this line exists.\n * That is why the trigger is written beside the code that would trip it rather than in the audit\n * that found it: a gap recorded in a reviewer's file reappears as a surprise; a gap recorded\n * here stops the person adding pruning.\n */\nexport async function lightPhase(\n facts: ReadonlyArray<MemoryFact>,\n embedding: EmbeddingRuntime,\n threshold: number = DEFAULT_DEDUP_THRESHOLD,\n): Promise<DedupResult> {\n if (facts.length <= 1) return { kept: [...facts], duplicatesRemoved: 0 };\n const never = facts.filter((f) => dedupPolicy(f) === \"never\");\n const exact = facts.filter((f) => dedupPolicy(f) === \"exact\");\n const similar = facts.filter((f) => dedupPolicy(f) === \"similar\");\n\n // Exact pass: identity, not similarity. No embedding call, no threshold, no judgement.\n const seen = new Set<string>();\n const exactKept: MemoryFact[] = [];\n let removed = 0;\n for (const f of exact) {\n const key = normalizeForExactMatch(f.text);\n if (seen.has(key)) {\n removed += 1;\n continue;\n }\n seen.add(key);\n exactKept.push(f);\n }\n\n const sim =\n similar.length > 1\n ? await dedupCandidates(similar, embedding, threshold)\n : { kept: [...similar], duplicatesRemoved: 0 };\n\n // Protected facts keep their original relative position at the front: they were never in\n // the running, and putting them back through the sort would imply they had been judged.\n return {\n kept: [...never, ...exactKept, ...sim.kept],\n duplicatesRemoved: removed + sim.duplicatesRemoved,\n };\n}\n\nasync function dedupCandidates(\n facts: ReadonlyArray<MemoryFact>,\n embedding: EmbeddingRuntime,\n threshold: number,\n): Promise<DedupResult> {\n if (facts.length <= 1) return { kept: [...facts], duplicatesRemoved: 0 };\n const vectors = await embedding.embed(facts.map((f) => f.text));\n const keptIdx: number[] = [];\n const keptVecs: number[][] = [];\n for (let i = 0; i < facts.length; i++) {\n const vec = vectors[i] ?? [];\n const isDup = keptVecs.some((kept) => cosineSimilarity(vec, kept) >= threshold);\n if (isDup) continue;\n keptIdx.push(i);\n keptVecs.push(vec);\n }\n const kept = keptIdx.map((i) => facts[i] as MemoryFact);\n return { kept, duplicatesRemoved: facts.length - kept.length };\n}\n\n// T4.6 — cap facts per sweep to prevent O(N²) blowup. 500 facts →\n// 125K comparisons (acceptable). 5000 facts → 12.5M (unacceptable).\n// When facts exceed the cap, a deterministic subsample is taken so the\n// sweep is bounded. The remaining facts are carried to the next sweep.\nconst DEFAULT_MAX_FACTS_PER_SWEEP = 500;\n\n/** REM phase — single-link agglomerative clustering by cosine similarity. */\nexport async function remPhase(\n facts: ReadonlyArray<MemoryFact>,\n embedding: EmbeddingRuntime,\n threshold: number = DEFAULT_CLUSTER_THRESHOLD,\n maxFactsPerSweep: number = DEFAULT_MAX_FACTS_PER_SWEEP,\n): Promise<ClusterResult> {\n // KNOWN GAP, deliberately not closed here. Protected kinds are excluded from DEDUP — a\n // near-duplicate correction is never dropped — but they still reach CLUSTERING, and a cluster\n // carries one representative into the consolidated note.\n //\n // Filtering them out here too was tried and reverted: untyped is the common case (hand-written\n // bullets carry no kind), so excluding it disables consolidation for most stores, and it broke\n // three existing golden tests. The damage is also smaller than in the dedup case — the source\n // files survive and remain readable, so what a cluster costs is nuance in an ADDITIONAL\n // artefact rather than a lost entry.\n //\n // It becomes real damage only if recall serves notes INSTEAD of sources. That depends on what\n // the index covers, which is not settled here. Recorded rather than silently accepted.\n if (facts.length === 0) return { clusters: [], factsLeftOut: 0 };\n // T4.6 — cap: subsample when facts exceed budget. Deterministic\n // sort by text hash so the same input always picks the same subset.\n const capped = facts.length > maxFactsPerSweep ? facts.slice(0, maxFactsPerSweep) : facts;\n const vectors = await embedding.embed(capped.map((f) => f.text));\n const clusterOfIdx = unionFindByPairs(vectors, threshold);\n const groups = bucketFactsByClusterRoot(capped, clusterOfIdx);\n return {\n clusters: [...groups.values()].map(buildClusterFromMembers),\n factsLeftOut: facts.length - capped.length,\n };\n}\n\nfunction unionFindByPairs(\n vectors: ReadonlyArray<ReadonlyArray<number>>,\n threshold: number,\n): number[] {\n const clusterOfIdx = vectors.map((_, i) => i);\n for (let i = 0; i < vectors.length; i++) {\n for (let j = i + 1; j < vectors.length; j++) {\n if (cosineSimilarity(vectors[i] ?? [], vectors[j] ?? []) >= threshold) {\n unifyClusters(clusterOfIdx, i, j);\n }\n }\n }\n return clusterOfIdx;\n}\n\nfunction bucketFactsByClusterRoot(\n facts: ReadonlyArray<MemoryFact>,\n clusterOfIdx: number[],\n): Map<number, MemoryFact[]> {\n const groups = new Map<number, MemoryFact[]>();\n for (let i = 0; i < facts.length; i++) {\n const root = findRoot(clusterOfIdx, i);\n const list = groups.get(root) ?? [];\n list.push(facts[i] as MemoryFact);\n groups.set(root, list);\n }\n return groups;\n}\n\nfunction buildClusterFromMembers(members: ReadonlyArray<MemoryFact>): Cluster {\n const sorted = [...members].sort((a, b) => b.text.length - a.text.length);\n return { representativeText: sorted[0]?.text ?? \"\", members };\n}\n\n/** Deep phase — render consolidated markdown for the dreamed note. */\nexport function deepPhase(clusters: ReadonlyArray<Cluster>, timestampMs: number): string {\n if (clusters.length === 0) return \"\";\n const isoStamp = new Date(timestampMs).toISOString();\n const lines: string[] = [`# Dreamed ${isoStamp}`, \"\"];\n for (let i = 0; i < clusters.length; i++) {\n const c = clusters[i];\n if (c === undefined) continue;\n lines.push(`## Cluster ${i + 1}: ${c.representativeText}`);\n lines.push(\"\");\n for (const member of c.members) lines.push(`- ${member.text}`);\n lines.push(\"\");\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction cosineSimilarity(a: ReadonlyArray<number>, b: ReadonlyArray<number>): number {\n if (a.length === 0 || b.length === 0 || a.length !== b.length) return 0;\n let dot = 0;\n let aNorm = 0;\n let bNorm = 0;\n for (let i = 0; i < a.length; i++) {\n const ai = a[i] ?? 0;\n const bi = b[i] ?? 0;\n dot += ai * bi;\n aNorm += ai * ai;\n bNorm += bi * bi;\n }\n const denom = Math.sqrt(aNorm) * Math.sqrt(bNorm);\n return denom === 0 ? 0 : dot / denom;\n}\n\nfunction findRoot(parents: number[], i: number): number {\n let root = i;\n while (parents[root] !== root) {\n const next = parents[root] ?? root;\n if (next === root) break;\n root = next;\n }\n parents[i] = root;\n return root;\n}\n\nfunction unifyClusters(parents: number[], a: number, b: number): void {\n const rootA = findRoot(parents, a);\n const rootB = findRoot(parents, b);\n if (rootA !== rootB) parents[rootB] = rootA;\n}\n","import { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { diag } from \"../../diagnostics.js\";\nimport { replaceFileAtomic } from \"../../persistence/atomic-write.js\";\nimport { withCwdMutex } from \"../../persistence/cwd-mutex.js\";\nimport type { EmbeddingRuntime } from \"../embedding-adapter.js\";\nimport { readFactsFromMarkdown } from \"../storage/markdown-store.js\";\nimport { type MemoryRoot, resolveMemoryRoot } from \"../storage/memory-root.js\";\nimport { appendDiaryEntry } from \"./diary.js\";\nimport { deepPhase, lightPhase, remPhase } from \"./phases.js\";\n\n/**\n * Dreaming sweep orchestrator (ADR D7 of memory-system-peer-project-parity).\n *\n * Phases:\n * 1. **light** — drop near-duplicate facts via cosine similarity.\n * 2. **REM** — cluster thematically related facts.\n * 3. **deep** — write a `notes/dreamed-<ts>.md` per sweep with consolidated\n * clusters; append a diary entry.\n *\n * All file writes go through `replaceFileAtomic` (EC-3) and the entire sweep\n * holds the per-cwd mutex so a `Remember:` append can't race it.\n */\n\nexport interface DreamingOptions {\n cwd: string;\n /**\n * The memory root to sweep. Defaults to the project store — right for a caller with no\n * `memory.directory`, and wrong for one that has it, which is why it is passable (#463).\n */\n memoryRoot?: MemoryRoot;\n embedding: EmbeddingRuntime;\n dedupThreshold?: number;\n clusterThreshold?: number;\n /** Test hook — fixed timestamp for the run. */\n now?: () => number;\n}\n\n/** Outcome of one dreaming sweep: counts before and after, and the note written. */\nexport interface DreamingResult {\n status: \"ok\" | \"skipped\" | \"error\";\n factsBefore: number;\n factsAfter: number;\n duplicatesRemoved: number;\n clustersCreated: number;\n notesWritten: number;\n diaryEntryHash: string | undefined;\n /**\n * Deduplicated facts past the per-sweep cap that were not clustered. Set on `\"ok\"`, 0 on\n * `\"skipped\"`, and absent on `\"error\"`, where the sweep cannot say how many it left out.\n */\n factsLeftOut?: number;\n}\n\n/** Run one dreaming sweep (dedupe, cluster, write a consolidated note), serialised per `cwd`. */\nexport function runDreamingSweep(options: DreamingOptions): Promise<DreamingResult> {\n return withCwdMutex(`dream:${options.cwd}`, () => runInner(options));\n}\n\nasync function runInner(options: DreamingOptions): Promise<DreamingResult> {\n const now = options.now ?? Date.now;\n const timestampMs = now();\n try {\n const root = options.memoryRoot ?? resolveMemoryRoot(options.cwd);\n const facts = await readFactsFromMarkdown(\n options.cwd,\n options.memoryRoot ? { directory: options.memoryRoot } : undefined,\n );\n if (facts.length === 0) {\n return emptyResult(\"skipped\");\n }\n const dedup = await lightPhase(facts, options.embedding, options.dedupThreshold);\n const rem = await remPhase(dedup.kept, options.embedding, options.clusterThreshold);\n const notesWritten = await writeConsolidatedNotes(root, rem.clusters, timestampMs);\n const result: DreamingResult = {\n status: \"ok\",\n factsBefore: facts.length,\n factsAfter: dedup.kept.length,\n duplicatesRemoved: dedup.duplicatesRemoved,\n clustersCreated: rem.clusters.length,\n notesWritten,\n diaryEntryHash: undefined,\n factsLeftOut: rem.factsLeftOut,\n };\n await appendDiaryEntry(root, {\n timestampMs,\n factsBefore: result.factsBefore,\n factsAfter: result.factsAfter,\n duplicatesRemoved: result.duplicatesRemoved,\n clustersCreated: result.clustersCreated,\n notesWritten: result.notesWritten,\n });\n return result;\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n diag(`[theokit-sdk] dreaming sweep failed: ${message}\\n`);\n return emptyResult(\"error\");\n }\n}\n\nasync function writeConsolidatedNotes(\n root: MemoryRoot,\n clusters: ReadonlyArray<{ representativeText: string; members: ReadonlyArray<{ text: string }> }>,\n timestampMs: number,\n): Promise<number> {\n if (clusters.length === 0) return 0;\n const notesDir = join(root, \"notes\");\n await mkdir(notesDir, { recursive: true });\n const isoSlug = new Date(timestampMs).toISOString().replace(/[^\\dT]/g, \"-\");\n const file = join(notesDir, `dreamed-${isoSlug}.md`);\n const body = deepPhase(clusters, timestampMs);\n await replaceFileAtomic(file, body);\n return 1;\n}\n\nfunction emptyResult(status: \"skipped\" | \"error\"): DreamingResult {\n const result: DreamingResult = {\n status,\n factsBefore: 0,\n factsAfter: 0,\n duplicatesRemoved: 0,\n clustersCreated: 0,\n notesWritten: 0,\n diaryEntryHash: undefined,\n };\n // An empty store left nothing out; a failed sweep cannot say, so it reports no count.\n return status === \"skipped\" ? { ...result, factsLeftOut: 0 } : result;\n}\n","import { existsSync, mkdirSync, renameSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { ConfigurationError } from \"../../errors.js\";\nimport { redactSecrets } from \"../security/index.js\";\nimport { defaultIndexPath, openMemoryDb } from \"./index-db.js\";\nimport { LanceIndex, lanceStoragePath } from \"./lance-index.js\";\nimport { type MemoryRoot, resolveMemoryRoot } from \"./storage/memory-root.js\";\n\n/**\n * Migrate Memory.index from SQLite to LanceDB (ADR D44).\n *\n * EC-3 MUST FIX: validation uses NFC unicode normalization on both sides.\n *\n * Shared with `@theokit/sdk-memory` through the memory-store barrel (#463).\n */\n\nexport interface MigrateOptions {\n cwd: string;\n /**\n * Absolute path (or `~/`-prefixed) of the memory root to migrate, when the agent that wrote it\n * set `memory.directory`. Defaults to `<cwd>/.theokit/memory` (#463).\n */\n directory?: string;\n dryRun?: boolean;\n batchSize?: number;\n /** Inject for tests; defaults to console.log. */\n logger?: (msg: string) => void;\n}\n\nexport interface MigrateResult {\n countSqlite: number;\n countLance: number;\n /** Set when validation succeeded (or dryRun); false on validation failure. */\n validated: boolean;\n /** Per-fact compare results (size = sample count, up to 10). */\n sampleComparisons: ReadonlyArray<{ id: string; match: boolean }>;\n /** Lance storage location (final, after migration). */\n lancePath: string;\n /** Was the migration committed (false for dry-run). */\n committed: boolean;\n}\n\n/**\n * One row of the SQLite memory index, as the Lance migration reads it: the chunk plus the tenant\n * columns the target table needs. Shared with `@theokit/sdk-memory`, which migrates the same table.\n */\nexport interface SqliteFactRow {\n id: string;\n path: string;\n source: \"memory\" | \"sessions\" | \"wiki\";\n start_line: number;\n end_line: number;\n text: string;\n namespace?: string | null;\n scope?: string | null;\n user_id?: string | null;\n}\n\n/**\n * Read all facts from the SQLite memory index. Returns empty array if the\n * SQLite db file does not exist (workspace never used Memory).\n *\n * Shared with `@theokit/sdk-memory` through the memory-store barrel, so it carries no visibility\n * tag — naming that tag in this block would delete the function below it (#463).\n */\nexport async function readAllSqliteFacts(root: MemoryRoot): Promise<SqliteFactRow[]> {\n const dbPath = defaultIndexPath(root);\n if (!existsSync(dbPath)) return [];\n const db = await openMemoryDb({ filePath: dbPath });\n try {\n // SQLite schema: chunks table holds the facts. Schema may vary; we\n // probe column existence and fall back to safe defaults.\n const stmt = db.prepare(\"SELECT id, path, source, start_line, end_line, text FROM chunks\");\n const rows = stmt.all() as Array<{\n id: string;\n path: string;\n source: \"memory\" | \"sessions\" | \"wiki\";\n start_line: number;\n end_line: number;\n text: string;\n }>;\n return rows.map((r) => ({\n ...r,\n namespace: \"default\",\n scope: \"agent\",\n user_id: \"default\",\n }));\n } finally {\n db.close();\n }\n}\n\n/**\n * Compare two strings via NFC normalization (EC-3 MUST FIX). Required\n * because SQLite/Lance native bindings can normalize unicode differently\n * (NFC vs NFD), producing false negatives on facts with accents/emojis.\n *\n * @internal\n */\nfunction nfcEqual(a: string, b: string): boolean {\n return a.normalize(\"NFC\") === b.normalize(\"NFC\");\n}\n\n/**\n * Refuse a `batchSize` the loop below cannot make progress with, before anything is migrated.\n *\n * The loop is `for (let i = 0; i < facts.length; i += batchSize)`, so the three ways this goes wrong\n * are all silent and all different:\n *\n * - 0 or negative: `i` never advances past the guard. The migration SPINS FOREVER, calling\n * `addFacts([])` and writing a \"Migrated x/y\" line every iteration — a hang with unbounded output,\n * which is the worst shape a failure can take because it looks like work.\n * - NaN (`Number(\"abc\")`): `i += NaN` makes the guard false on the first check, zero facts move, and\n * the caller is told \"Validation FAILED. SQLite preserved.\" A typo in an argument is reported as a\n * migration failure.\n * - a fraction: `slice` truncates and the loop still terminates, but the batch boundaries stop\n * matching the number the caller asked for.\n *\n * Validated HERE rather than only in the CLI that motivated the finding, because the CLI is a wrapper\n * over this function and a programmatic caller reaches it with no wrapper at all.\n *\n * @internal\n */\nfunction assertUsableBatchSize(batchSize: number | undefined): void {\n if (batchSize === undefined) return;\n if (!Number.isInteger(batchSize) || batchSize < 1) {\n throw new ConfigurationError(\n `migrateSqliteToLance: batchSize must be a whole number of at least 1; received ${String(batchSize)}.`,\n { code: \"invalid_batch_size\" },\n );\n }\n}\n\n/**\n * Run the migration. Writes Lance to `<cwd>/.theokit/memory/lance-new/`\n * first, validates round-trip, then renames to `lance/` on success.\n * SQLite db is preserved (CLI prompts user to delete).\n *\n * @internal\n */\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: migration is a single transaction (read → write → validate → commit-or-rollback); splitting harms atomicity reasoning.\nexport async function migrateSqliteToLance(opts: MigrateOptions): Promise<MigrateResult> {\n assertUsableBatchSize(opts.batchSize);\n const cwd = opts.cwd;\n // One resolution, reused by every path this migration touches (#463).\n const memoryRoot = resolveMemoryRoot(cwd, { directory: opts.directory });\n const finalPath = lanceStoragePath(memoryRoot);\n const newPath = join(memoryRoot, \"lance-new\");\n // T1.4 (ADR D68): wrap logger so any fact text containing secrets is\n // masked before reaching the destination (console or user-supplied sink).\n // Caller-supplied loggers cannot bypass — by design (D70).\n const rawLog = opts.logger ?? ((m: string) => console.log(m));\n const log = (m: string) => rawLog(redactSecrets(m));\n\n // EC: destination exists → typed error.\n if (existsSync(finalPath)) {\n throw new ConfigurationError(\n `Destination already exists: ${finalPath}. Remove it manually (\\`rm -rf ${finalPath}\\`) and re-run.`,\n { code: \"migration_destination_exists\" },\n );\n }\n if (existsSync(newPath)) {\n // Leftover from a previous failed/interrupted migration. Safe to delete.\n log(`Removing stale ${newPath} from a previous run...`);\n rmSync(newPath, { recursive: true, force: true });\n }\n\n log(`Reading SQLite facts from ${cwd}/.theokit/memory/index.sqlite ...`);\n const sqliteFacts = await readAllSqliteFacts(memoryRoot);\n log(`SQLite has ${sqliteFacts.length} facts.`);\n if (sqliteFacts.length === 0) {\n return {\n countSqlite: 0,\n countLance: 0,\n validated: true,\n sampleComparisons: [],\n lancePath: finalPath,\n committed: false,\n };\n }\n\n // Reuse the embedding runtime configured in the workspace? For v1.2 we\n // require the caller to pass embedding explicitly via env. The migration\n // path is documented as: \"set OPENAI_API_KEY (or similar) before running.\"\n // Here we ship a placeholder embedder that uses a deterministic\n // content-hash — sufficient for migration validation; consumers should\n // re-embed on first real query after migration if needed.\n const placeholderEmbedding = {\n id: \"migration-placeholder\",\n model: \"deterministic-hash\",\n dimension: 8,\n embed: async (texts: ReadonlyArray<string>) => {\n // Simple deterministic hash → 8-dim vector (migration validation only).\n return texts.map((t) => {\n const arr = new Array(8).fill(0);\n for (let i = 0; i < t.length; i += 1) {\n arr[i % 8] += t.charCodeAt(i);\n }\n return arr.map((x) => x / 1000);\n });\n },\n stats: () => ({ cacheHits: 0, cacheMisses: 0, httpCalls: 0, retries: 0 }),\n };\n\n mkdirSync(newPath, { recursive: true });\n log(`Writing Lance index to ${newPath} ...`);\n\n const lance = await LanceIndex.open({\n cwd,\n embedding: placeholderEmbedding,\n storagePath: newPath,\n });\n\n const batchSize = opts.batchSize ?? 100;\n for (let i = 0; i < sqliteFacts.length; i += batchSize) {\n const batch = sqliteFacts.slice(i, i + batchSize).map((f) => ({\n id: f.id,\n text: f.text,\n source: f.source,\n namespace: f.namespace ?? \"default\",\n scope: f.scope ?? \"agent\",\n user_id: f.user_id ?? \"default\",\n timestamp: 0,\n }));\n await lance.addFacts(batch);\n log(` Migrated ${Math.min(i + batchSize, sqliteFacts.length)}/${sqliteFacts.length}`);\n }\n\n // Validation: count + sample compare (10 random) with NFC normalization.\n const lanceCount = await lance.countFacts(\"default\");\n log(`Lance has ${lanceCount} facts (expected ${sqliteFacts.length}).`);\n\n const sampleSize = Math.min(10, sqliteFacts.length);\n const sampleComparisons: { id: string; match: boolean }[] = [];\n for (let i = 0; i < sampleSize; i += 1) {\n const sqliteFact = sqliteFacts[Math.floor((i * sqliteFacts.length) / sampleSize)];\n if (sqliteFact === undefined) continue;\n // Search Lance for this fact's text — best-effort round-trip.\n const hits = await lance.search(sqliteFact.text, {\n namespace: sqliteFact.namespace ?? \"default\",\n limit: 1,\n });\n // EC-3: compare with NFC normalization.\n const hit = hits[0];\n const match = hit !== undefined && nfcEqual(hit.text, sqliteFact.text);\n sampleComparisons.push({ id: sqliteFact.id, match });\n }\n\n const allMatch = sampleComparisons.every((c) => c.match);\n const countMatch = lanceCount === sqliteFacts.length;\n const validated = allMatch && countMatch;\n\n await lance.close();\n\n if (opts.dryRun === true) {\n log(\"Dry-run mode — discarding Lance staging dir.\");\n rmSync(newPath, { recursive: true, force: true });\n return {\n countSqlite: sqliteFacts.length,\n countLance: lanceCount,\n validated,\n sampleComparisons,\n lancePath: finalPath,\n committed: false,\n };\n }\n\n if (!validated) {\n log(\"Validation FAILED — leaving SQLite intact, removing Lance staging dir.\");\n rmSync(newPath, { recursive: true, force: true });\n return {\n countSqlite: sqliteFacts.length,\n countLance: lanceCount,\n validated: false,\n sampleComparisons,\n lancePath: finalPath,\n committed: false,\n };\n }\n\n // Atomic commit via rename.\n renameSync(newPath, finalPath);\n log(`Migration committed to ${finalPath}.`);\n return {\n countSqlite: sqliteFacts.length,\n countLance: lanceCount,\n validated: true,\n sampleComparisons,\n lancePath: finalPath,\n committed: true,\n };\n}\n"]}