@theokit/sdk 4.52.1 → 4.53.1

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 (385) hide show
  1. package/CHANGELOG.md +48 -8
  2. package/LICENSE +2 -2
  3. package/README.md +5 -5
  4. package/bin/theokit-migrate-config.mjs +11 -2
  5. package/dist/{agent-BiCINq25.d.ts → agent-B9HXlwID.d.ts} +21 -8
  6. package/dist/agent-FFVV4U5N.js +50 -0
  7. package/dist/{agent-RDHK6MVT.js.map → agent-FFVV4U5N.js.map} +1 -1
  8. package/dist/agent-YLAHVHEH.cjs +59 -0
  9. package/dist/{agent-U2R2R5JP.cjs.map → agent-YLAHVHEH.cjs.map} +1 -1
  10. package/dist/{agent-Zta1kvGH.d.cts → agent-nLqeXKIX.d.cts} +21 -8
  11. package/dist/agent-session-store-DUGBAX5V.cjs +23 -0
  12. package/dist/{agent-session-store-EPX2WQI4.cjs.map → agent-session-store-DUGBAX5V.cjs.map} +1 -1
  13. package/dist/agent-session-store-TNCGL5RN.js +6 -0
  14. package/dist/{agent-session-store-JMU7ASDB.js.map → agent-session-store-TNCGL5RN.js.map} +1 -1
  15. package/dist/agent.d.ts +16 -1
  16. package/dist/auth/index.cjs +29 -28
  17. package/dist/auth/index.cjs.map +1 -1
  18. package/dist/auth/index.d.cts +1 -1
  19. package/dist/auth/index.d.ts +1 -1
  20. package/dist/auth/index.js +6 -5
  21. package/dist/auth/index.js.map +1 -1
  22. package/dist/{batch-NLIS4QTW.js → batch-UPKN4SG6.js} +9 -9
  23. package/dist/{batch-NLIS4QTW.js.map → batch-UPKN4SG6.js.map} +1 -1
  24. package/dist/{batch-WQ3AJCDV.cjs → batch-ZEFN5SO7.cjs} +26 -26
  25. package/dist/{batch-WQ3AJCDV.cjs.map → batch-ZEFN5SO7.cjs.map} +1 -1
  26. package/dist/{chunk-CY7MIMI4.cjs → chunk-2D43RD5D.cjs} +8 -8
  27. package/dist/{chunk-CY7MIMI4.cjs.map → chunk-2D43RD5D.cjs.map} +1 -1
  28. package/dist/{chunk-WLESQ3ZQ.cjs → chunk-2FYEVT2B.cjs} +121 -121
  29. package/dist/{chunk-WLESQ3ZQ.cjs.map → chunk-2FYEVT2B.cjs.map} +1 -1
  30. package/dist/{chunk-BBZYXVLZ.cjs → chunk-2ZPEDVLM.cjs} +2 -2
  31. package/dist/chunk-2ZPEDVLM.cjs.map +1 -0
  32. package/dist/{chunk-T6QUCG7L.cjs → chunk-3BK6YR5P.cjs} +4 -4
  33. package/dist/{chunk-T6QUCG7L.cjs.map → chunk-3BK6YR5P.cjs.map} +1 -1
  34. package/dist/chunk-3V7UJLQT.js +147 -0
  35. package/dist/chunk-3V7UJLQT.js.map +1 -0
  36. package/dist/{chunk-ITQ4NO4P.js → chunk-3WVMJY7F.js} +3 -3
  37. package/dist/{chunk-ITQ4NO4P.js.map → chunk-3WVMJY7F.js.map} +1 -1
  38. package/dist/{chunk-RAACTJ7C.cjs → chunk-3X6PM7DU.cjs} +4 -4
  39. package/dist/{chunk-RAACTJ7C.cjs.map → chunk-3X6PM7DU.cjs.map} +1 -1
  40. package/dist/{chunk-DEZ75ET5.js → chunk-4Q4K4WB5.js} +3 -3
  41. package/dist/{chunk-DEZ75ET5.js.map → chunk-4Q4K4WB5.js.map} +1 -1
  42. package/dist/{chunk-4X3SBHPK.js → chunk-5F5NWKPN.js} +20 -4
  43. package/dist/chunk-5F5NWKPN.js.map +1 -0
  44. package/dist/chunk-5YKNEMXR.cjs +155 -0
  45. package/dist/chunk-5YKNEMXR.cjs.map +1 -0
  46. package/dist/{chunk-3YYDHUNH.cjs → chunk-665SFFFR.cjs} +11 -11
  47. package/dist/{chunk-3YYDHUNH.cjs.map → chunk-665SFFFR.cjs.map} +1 -1
  48. package/dist/{chunk-CHVSMEKM.js → chunk-6AZDM6LK.js} +3 -3
  49. package/dist/chunk-6AZDM6LK.js.map +1 -0
  50. package/dist/{chunk-AMYY3JHQ.cjs → chunk-ADLLFY3H.cjs} +9 -9
  51. package/dist/{chunk-AMYY3JHQ.cjs.map → chunk-ADLLFY3H.cjs.map} +1 -1
  52. package/dist/{chunk-J4RY5DTI.js → chunk-B6HOIWQ6.js} +5 -5
  53. package/dist/{chunk-J4RY5DTI.js.map → chunk-B6HOIWQ6.js.map} +1 -1
  54. package/dist/{chunk-EQMLJ52C.cjs → chunk-BDTVFIPB.cjs} +26 -26
  55. package/dist/{chunk-EQMLJ52C.cjs.map → chunk-BDTVFIPB.cjs.map} +1 -1
  56. package/dist/{chunk-UJ3SXRZZ.js → chunk-BERBYXFH.js} +3 -3
  57. package/dist/{chunk-UJ3SXRZZ.js.map → chunk-BERBYXFH.js.map} +1 -1
  58. package/dist/{chunk-KZBB4YKU.js → chunk-BFYGJGC5.js} +3 -3
  59. package/dist/{chunk-KZBB4YKU.js.map → chunk-BFYGJGC5.js.map} +1 -1
  60. package/dist/{chunk-SXSPMRSV.cjs → chunk-BM6N4KHO.cjs} +21 -3
  61. package/dist/chunk-BM6N4KHO.cjs.map +1 -0
  62. package/dist/{chunk-2CFEET3Y.cjs → chunk-C4H6PB5J.cjs} +4 -4
  63. package/dist/chunk-C4H6PB5J.cjs.map +1 -0
  64. package/dist/{chunk-NFATC6ZF.cjs → chunk-C5DEO6OI.cjs} +4 -4
  65. package/dist/{chunk-NFATC6ZF.cjs.map → chunk-C5DEO6OI.cjs.map} +1 -1
  66. package/dist/{chunk-EUBGGYPH.cjs → chunk-CZ2GKKYL.cjs} +5 -5
  67. package/dist/{chunk-EUBGGYPH.cjs.map → chunk-CZ2GKKYL.cjs.map} +1 -1
  68. package/dist/{chunk-I732VEDW.js → chunk-D24WJWN2.js} +3 -3
  69. package/dist/{chunk-I732VEDW.js.map → chunk-D24WJWN2.js.map} +1 -1
  70. package/dist/{chunk-3R4ZCQAZ.cjs → chunk-D75S2X6I.cjs} +5 -5
  71. package/dist/{chunk-3R4ZCQAZ.cjs.map → chunk-D75S2X6I.cjs.map} +1 -1
  72. package/dist/{chunk-5XXUYU3M.js → chunk-DGOG5NXR.js} +3 -3
  73. package/dist/{chunk-5XXUYU3M.js.map → chunk-DGOG5NXR.js.map} +1 -1
  74. package/dist/{chunk-RTLUZKDL.cjs → chunk-E7FJOO4G.cjs} +11 -11
  75. package/dist/{chunk-RTLUZKDL.cjs.map → chunk-E7FJOO4G.cjs.map} +1 -1
  76. package/dist/{chunk-BWGXYOBZ.cjs → chunk-ELKO4ZLR.cjs} +4 -4
  77. package/dist/{chunk-BWGXYOBZ.cjs.map → chunk-ELKO4ZLR.cjs.map} +1 -1
  78. package/dist/{chunk-FBZMSLDC.cjs → chunk-EZ2YEF4F.cjs} +4 -4
  79. package/dist/{chunk-FBZMSLDC.cjs.map → chunk-EZ2YEF4F.cjs.map} +1 -1
  80. package/dist/{chunk-6GS7JI64.cjs → chunk-F77UENR6.cjs} +343 -324
  81. package/dist/chunk-F77UENR6.cjs.map +1 -0
  82. package/dist/{chunk-OZXPA3ME.js → chunk-FFM3SJTQ.js} +4 -4
  83. package/dist/{chunk-OZXPA3ME.js.map → chunk-FFM3SJTQ.js.map} +1 -1
  84. package/dist/{chunk-PLUCC4N5.js → chunk-FIOCJYLA.js} +3 -3
  85. package/dist/{chunk-PLUCC4N5.js.map → chunk-FIOCJYLA.js.map} +1 -1
  86. package/dist/{chunk-Z5U2JGEK.cjs → chunk-FOXKFTVZ.cjs} +11 -11
  87. package/dist/{chunk-Z5U2JGEK.cjs.map → chunk-FOXKFTVZ.cjs.map} +1 -1
  88. package/dist/{chunk-K42QGAKM.cjs → chunk-FPYT5WZP.cjs} +10 -10
  89. package/dist/{chunk-K42QGAKM.cjs.map → chunk-FPYT5WZP.cjs.map} +1 -1
  90. package/dist/{chunk-KELIQH7K.js → chunk-G3JWXOGY.js} +78 -58
  91. package/dist/chunk-G3JWXOGY.js.map +1 -0
  92. package/dist/{chunk-DHVNJYTO.js → chunk-GBBDINFK.js} +3 -3
  93. package/dist/{chunk-DHVNJYTO.js.map → chunk-GBBDINFK.js.map} +1 -1
  94. package/dist/{chunk-V45L2OYP.cjs → chunk-GD63JPGC.cjs} +9 -9
  95. package/dist/{chunk-V45L2OYP.cjs.map → chunk-GD63JPGC.cjs.map} +1 -1
  96. package/dist/{chunk-42PLABFU.js → chunk-GOVJO4YE.js} +5 -5
  97. package/dist/{chunk-42PLABFU.js.map → chunk-GOVJO4YE.js.map} +1 -1
  98. package/dist/{chunk-CZHPR2G7.cjs → chunk-HAWE74GQ.cjs} +8 -8
  99. package/dist/{chunk-CZHPR2G7.cjs.map → chunk-HAWE74GQ.cjs.map} +1 -1
  100. package/dist/{chunk-KIX45IKP.js → chunk-HE4BIAOS.js} +4 -4
  101. package/dist/{chunk-KIX45IKP.js.map → chunk-HE4BIAOS.js.map} +1 -1
  102. package/dist/{chunk-AM2CNBKE.js → chunk-HKCKOAIO.js} +2 -2
  103. package/dist/chunk-HKCKOAIO.js.map +1 -0
  104. package/dist/{chunk-V2EJLKGA.js → chunk-HSQ5Q3I5.js} +10 -11
  105. package/dist/chunk-HSQ5Q3I5.js.map +1 -0
  106. package/dist/{chunk-QLAWEGTZ.cjs → chunk-JIQRXKTA.cjs} +7 -7
  107. package/dist/chunk-JIQRXKTA.cjs.map +1 -0
  108. package/dist/{chunk-EFXJ5C7X.js → chunk-KSWHTR54.js} +5 -5
  109. package/dist/{chunk-EFXJ5C7X.js.map → chunk-KSWHTR54.js.map} +1 -1
  110. package/dist/{chunk-6PTCKXD3.js → chunk-LD4MOBFX.js} +8 -8
  111. package/dist/{chunk-6PTCKXD3.js.map → chunk-LD4MOBFX.js.map} +1 -1
  112. package/dist/{chunk-2YGIBOUH.cjs → chunk-LPVIRJVF.cjs} +9 -9
  113. package/dist/chunk-LPVIRJVF.cjs.map +1 -0
  114. package/dist/{chunk-M5EK7N6R.js → chunk-LS3LMQ23.js} +9 -9
  115. package/dist/{chunk-M5EK7N6R.js.map → chunk-LS3LMQ23.js.map} +1 -1
  116. package/dist/{chunk-N43XLTHZ.js → chunk-LTSTGCL6.js} +3 -3
  117. package/dist/{chunk-N43XLTHZ.js.map → chunk-LTSTGCL6.js.map} +1 -1
  118. package/dist/{chunk-W4FV7JBH.js → chunk-MSFLYJDY.js} +4 -4
  119. package/dist/chunk-MSFLYJDY.js.map +1 -0
  120. package/dist/{chunk-C4EU627W.js → chunk-N5CR3TJZ.js} +4 -4
  121. package/dist/{chunk-C4EU627W.js.map → chunk-N5CR3TJZ.js.map} +1 -1
  122. package/dist/{chunk-NACDF3PK.js → chunk-NZL4BNFQ.js} +4 -4
  123. package/dist/chunk-NZL4BNFQ.js.map +1 -0
  124. package/dist/{chunk-OI6RHLGC.cjs → chunk-OUOXM36O.cjs} +11 -11
  125. package/dist/{chunk-OI6RHLGC.cjs.map → chunk-OUOXM36O.cjs.map} +1 -1
  126. package/dist/{chunk-BXVSBYGW.js → chunk-OY7O3Q6R.js} +5 -5
  127. package/dist/{chunk-BXVSBYGW.js.map → chunk-OY7O3Q6R.js.map} +1 -1
  128. package/dist/{chunk-L7EGRCKJ.js → chunk-PBZ7HMBP.js} +4 -4
  129. package/dist/{chunk-L7EGRCKJ.js.map → chunk-PBZ7HMBP.js.map} +1 -1
  130. package/dist/{chunk-OIBHY6JQ.js → chunk-PGP7IOJ2.js} +4 -4
  131. package/dist/{chunk-OIBHY6JQ.js.map → chunk-PGP7IOJ2.js.map} +1 -1
  132. package/dist/{chunk-R7TKOQMJ.js → chunk-POWRZSK4.js} +3 -3
  133. package/dist/{chunk-R7TKOQMJ.js.map → chunk-POWRZSK4.js.map} +1 -1
  134. package/dist/{chunk-R3CKCRK3.cjs → chunk-Q4RESANI.cjs} +4 -4
  135. package/dist/{chunk-R3CKCRK3.cjs.map → chunk-Q4RESANI.cjs.map} +1 -1
  136. package/dist/{chunk-ZNEE4WWQ.cjs → chunk-QBTVATSF.cjs} +25 -24
  137. package/dist/chunk-QBTVATSF.cjs.map +1 -0
  138. package/dist/{chunk-ZSJPRPN7.js → chunk-R5YZACGK.js} +3 -3
  139. package/dist/{chunk-ZSJPRPN7.js.map → chunk-R5YZACGK.js.map} +1 -1
  140. package/dist/{chunk-ADVZIC43.cjs → chunk-RAHSWE5C.cjs} +10 -10
  141. package/dist/{chunk-ADVZIC43.cjs.map → chunk-RAHSWE5C.cjs.map} +1 -1
  142. package/dist/{chunk-NOS7PTKP.js → chunk-SEL2ZQMT.js} +7 -7
  143. package/dist/{chunk-NOS7PTKP.js.map → chunk-SEL2ZQMT.js.map} +1 -1
  144. package/dist/{chunk-XWCTBGYK.js → chunk-SK4QLUBK.js} +3 -3
  145. package/dist/chunk-SK4QLUBK.js.map +1 -0
  146. package/dist/chunk-SSDD676S.js +171 -0
  147. package/dist/chunk-SSDD676S.js.map +1 -0
  148. package/dist/{chunk-E3OCRJU6.cjs → chunk-SVO5WPZX.cjs} +11 -11
  149. package/dist/{chunk-E3OCRJU6.cjs.map → chunk-SVO5WPZX.cjs.map} +1 -1
  150. package/dist/{chunk-44IISBRZ.cjs → chunk-SZHU7A5B.cjs} +4 -4
  151. package/dist/{chunk-44IISBRZ.cjs.map → chunk-SZHU7A5B.cjs.map} +1 -1
  152. package/dist/{chunk-SDJYLCJK.cjs → chunk-TTJ54H3E.cjs} +6 -6
  153. package/dist/chunk-TTJ54H3E.cjs.map +1 -0
  154. package/dist/{chunk-HI4ZW62S.js → chunk-U4UJHOSH.js} +4 -4
  155. package/dist/chunk-U4UJHOSH.js.map +1 -0
  156. package/dist/{chunk-XGYI2KQH.js → chunk-UFIXH26P.js} +4 -4
  157. package/dist/{chunk-XGYI2KQH.js.map → chunk-UFIXH26P.js.map} +1 -1
  158. package/dist/{chunk-JJZ4NIAG.js → chunk-V26QVGUG.js} +7 -6
  159. package/dist/chunk-V26QVGUG.js.map +1 -0
  160. package/dist/{chunk-GNPI5IWZ.js → chunk-V6HWJQQV.js} +6 -5
  161. package/dist/chunk-V6HWJQQV.js.map +1 -0
  162. package/dist/{chunk-MV4TOCUK.js → chunk-VC5ABJXC.js} +3 -3
  163. package/dist/{chunk-MV4TOCUK.js.map → chunk-VC5ABJXC.js.map} +1 -1
  164. package/dist/chunk-VF7X6HDR.cjs +177 -0
  165. package/dist/chunk-VF7X6HDR.cjs.map +1 -0
  166. package/dist/{chunk-7HQVDLFI.cjs → chunk-VGPXHHF3.cjs} +11 -9
  167. package/dist/chunk-VGPXHHF3.cjs.map +1 -0
  168. package/dist/{chunk-T6ZCG5AP.cjs → chunk-VUKQL3L2.cjs} +18 -19
  169. package/dist/chunk-VUKQL3L2.cjs.map +1 -0
  170. package/dist/{chunk-PVBANCWU.cjs → chunk-VW6M4B3Z.cjs} +5 -5
  171. package/dist/{chunk-PVBANCWU.cjs.map → chunk-VW6M4B3Z.cjs.map} +1 -1
  172. package/dist/{chunk-KNZU4YO5.cjs → chunk-WQ53UQL4.cjs} +4 -4
  173. package/dist/{chunk-KNZU4YO5.cjs.map → chunk-WQ53UQL4.cjs.map} +1 -1
  174. package/dist/{chunk-6DCTL32L.cjs → chunk-XPR366DL.cjs} +17 -17
  175. package/dist/{chunk-6DCTL32L.cjs.map → chunk-XPR366DL.cjs.map} +1 -1
  176. package/dist/{chunk-7TB5U7RK.js → chunk-XROIW6BH.js} +6 -6
  177. package/dist/{chunk-7TB5U7RK.js.map → chunk-XROIW6BH.js.map} +1 -1
  178. package/dist/{chunk-ECPL5RV6.cjs → chunk-Y4AXQOT4.cjs} +8 -8
  179. package/dist/{chunk-ECPL5RV6.cjs.map → chunk-Y4AXQOT4.cjs.map} +1 -1
  180. package/dist/{chunk-E6T264NS.js → chunk-Y4I4EQFK.js} +3 -3
  181. package/dist/{chunk-E6T264NS.js.map → chunk-Y4I4EQFK.js.map} +1 -1
  182. package/dist/{chunk-FUASIT3E.cjs → chunk-ZN2DGEY3.cjs} +15 -15
  183. package/dist/{chunk-FUASIT3E.cjs.map → chunk-ZN2DGEY3.cjs.map} +1 -1
  184. package/dist/{chunk-YTO5BRBD.cjs → chunk-ZT57WTUJ.cjs} +8 -8
  185. package/dist/chunk-ZT57WTUJ.cjs.map +1 -0
  186. package/dist/compact-session-4MNKNMO2.js +21 -0
  187. package/dist/{compact-session-XLXC2CZN.js.map → compact-session-4MNKNMO2.js.map} +1 -1
  188. package/dist/compact-session-EPFBQ46Z.cjs +58 -0
  189. package/dist/{compact-session-FBVWO6B3.cjs.map → compact-session-EPFBQ46Z.cjs.map} +1 -1
  190. package/dist/compaction.cjs +16 -16
  191. package/dist/compaction.js +3 -3
  192. package/dist/concurrency.cjs +6 -6
  193. package/dist/concurrency.js +4 -4
  194. package/dist/context-7USNN6LP.cjs +22 -0
  195. package/dist/{context-4HGPCOH6.cjs.map → context-7USNN6LP.cjs.map} +1 -1
  196. package/dist/context-ENXZNF6J.js +5 -0
  197. package/dist/{context-DCECDKWN.js.map → context-ENXZNF6J.js.map} +1 -1
  198. package/dist/{cron-DyWQsEG6.d.ts → cron-BMjgFH-_.d.ts} +1 -1
  199. package/dist/{cron-DgHJnMAK.d.cts → cron-DFDdCdMM.d.cts} +1 -1
  200. package/dist/cron.cjs +33 -32
  201. package/dist/cron.d.cts +2 -2
  202. package/dist/cron.d.ts +2 -2
  203. package/dist/cron.js +32 -31
  204. package/dist/errors.cjs +21 -21
  205. package/dist/errors.js +2 -2
  206. package/dist/eval.cjs +43 -42
  207. package/dist/eval.cjs.map +1 -1
  208. package/dist/eval.js +33 -32
  209. package/dist/eval.js.map +1 -1
  210. package/dist/{executor-4SW7QGZ4.cjs → executor-2Z3LGG3I.cjs} +24 -24
  211. package/dist/{executor-4SW7QGZ4.cjs.map → executor-2Z3LGG3I.cjs.map} +1 -1
  212. package/dist/{executor-3CGPLVJL.js → executor-2Z6XJJJG.js} +7 -7
  213. package/dist/{executor-3CGPLVJL.js.map → executor-2Z6XJJJG.js.map} +1 -1
  214. package/dist/filesystem/index.cjs +7 -7
  215. package/dist/filesystem/index.js +3 -3
  216. package/dist/fs-session-store-R5FD3EN6.js +10 -0
  217. package/dist/{fs-session-store-2TF3ZWMT.js.map → fs-session-store-R5FD3EN6.js.map} +1 -1
  218. package/dist/fs-session-store-VVY2AHWG.cjs +19 -0
  219. package/dist/{fs-session-store-TL4RJTXZ.cjs.map → fs-session-store-VVY2AHWG.cjs.map} +1 -1
  220. package/dist/generate-object-AVXOJK2I.cjs +20 -0
  221. package/dist/{generate-object-E465DX5I.cjs.map → generate-object-AVXOJK2I.cjs.map} +1 -1
  222. package/dist/generate-object-WQRCXFD2.js +7 -0
  223. package/dist/{generate-object-TVQCW2IZ.js.map → generate-object-WQRCXFD2.js.map} +1 -1
  224. package/dist/index-manager-VRU3A2YL.cjs +21 -0
  225. package/dist/{index-manager-HGGL4DD5.cjs.map → index-manager-VRU3A2YL.cjs.map} +1 -1
  226. package/dist/index-manager-WS7TVKUW.js +12 -0
  227. package/dist/{index-manager-EA6FGIQG.js.map → index-manager-WS7TVKUW.js.map} +1 -1
  228. package/dist/index.cjs +143 -134
  229. package/dist/index.cjs.map +1 -1
  230. package/dist/index.d.cts +64 -8
  231. package/dist/index.d.ts +64 -8
  232. package/dist/index.js +45 -44
  233. package/dist/index.js.map +1 -1
  234. package/dist/{inject-session-UBAQ7I3G.cjs → inject-session-AUQLBDRS.cjs} +9 -9
  235. package/dist/{inject-session-UBAQ7I3G.cjs.map → inject-session-AUQLBDRS.cjs.map} +1 -1
  236. package/dist/{inject-session-UEH5MAKU.js → inject-session-GMBMJVNZ.js} +7 -7
  237. package/dist/{inject-session-UEH5MAKU.js.map → inject-session-GMBMJVNZ.js.map} +1 -1
  238. package/dist/internal/auth/auth-types.d.ts +1 -1
  239. package/dist/internal/auth/oauth-device.d.ts +2 -2
  240. package/dist/internal/local-agent/mcp-pool.d.ts +2 -4
  241. package/dist/internal/mcp/oauth.d.ts +14 -0
  242. package/dist/internal/mcp/token-storage.d.ts +18 -0
  243. package/dist/internal/memory/adapters/index.cjs +8 -8
  244. package/dist/internal/memory/adapters/index.js +7 -7
  245. package/dist/internal/persistence/atomic-write.d.cts +93 -0
  246. package/dist/internal/persistence/atomic-write.d.ts +93 -0
  247. package/dist/internal/persistence/file-lock.d.cts +13 -1
  248. package/dist/internal/persistence/file-lock.d.ts +13 -1
  249. package/dist/internal/persistence/fts5-sanitize.d.cts +9 -1
  250. package/dist/internal/persistence/fts5-sanitize.d.ts +9 -1
  251. package/dist/internal/persistence/index.cjs +25 -25
  252. package/dist/internal/persistence/index.js +6 -6
  253. package/dist/internal/persistence/session-dir.d.cts +1 -0
  254. package/dist/internal/persistence/session-dir.d.ts +1 -0
  255. package/dist/internal/persistence/session-writer.d.cts +13 -0
  256. package/dist/internal/persistence/session-writer.d.ts +13 -0
  257. package/dist/internal/persistence/sqlite-wal.d.cts +9 -1
  258. package/dist/internal/persistence/sqlite-wal.d.ts +9 -1
  259. package/dist/internal/persistence/transcript-ops.d.cts +6 -7
  260. package/dist/internal/persistence/transcript-ops.d.ts +6 -7
  261. package/dist/internal/providers/builtin/cerebras.d.ts +2 -2
  262. package/dist/internal/providers/builtin/deepinfra.d.ts +1 -1
  263. package/dist/internal/providers/catalog-source-models-dev.d.ts +1 -1
  264. package/dist/internal/runtime/lifecycle/env-policy.d.ts +1 -3
  265. package/dist/internal/security/index.cjs +13 -13
  266. package/dist/internal/security/index.js +3 -3
  267. package/dist/internal/security/path-guard.d.cts +61 -0
  268. package/dist/internal/security/path-guard.d.ts +61 -0
  269. package/dist/internal/session/compact-session.d.ts +2 -2
  270. package/dist/internal/telemetry/tracer.d.ts +24 -0
  271. package/dist/judge-call-G5SGV2M2.cjs +22 -0
  272. package/dist/{judge-call-GVIJWQVE.cjs.map → judge-call-G5SGV2M2.cjs.map} +1 -1
  273. package/dist/judge-call-MDIPTBJI.js +5 -0
  274. package/dist/{judge-call-QMKGC2ZK.js.map → judge-call-MDIPTBJI.js.map} +1 -1
  275. package/dist/mcp-auth.cjs +299 -0
  276. package/dist/mcp-auth.cjs.map +1 -0
  277. package/dist/mcp-auth.d.cts +17 -0
  278. package/dist/mcp-auth.d.ts +17 -0
  279. package/dist/mcp-auth.js +292 -0
  280. package/dist/mcp-auth.js.map +1 -0
  281. package/dist/models.cjs +22 -21
  282. package/dist/models.cjs.map +1 -1
  283. package/dist/models.js +7 -6
  284. package/dist/models.js.map +1 -1
  285. package/dist/path-safety.cjs +10 -10
  286. package/dist/path-safety.js +3 -3
  287. package/dist/persistence.cjs +38 -29
  288. package/dist/persistence.cjs.map +1 -1
  289. package/dist/persistence.js +18 -9
  290. package/dist/persistence.js.map +1 -1
  291. package/dist/project.cjs +5 -5
  292. package/dist/project.js +3 -3
  293. package/dist/registry-63ASMXT4.cjs +46 -0
  294. package/dist/{registry-UBY26R4I.cjs.map → registry-63ASMXT4.cjs.map} +1 -1
  295. package/dist/registry-O7FJ2MPM.js +9 -0
  296. package/dist/{registry-GC7BQMSV.js.map → registry-O7FJ2MPM.js.map} +1 -1
  297. package/dist/retry.cjs +4 -4
  298. package/dist/retry.js +3 -3
  299. package/dist/sandbox/bwrap.d.cts +1 -2
  300. package/dist/sandbox/bwrap.d.ts +1 -2
  301. package/dist/sandbox/index.cjs +20 -20
  302. package/dist/sandbox/index.cjs.map +1 -1
  303. package/dist/sandbox/index.js +5 -5
  304. package/dist/sandbox/index.js.map +1 -1
  305. package/dist/server/errors-envelope.cjs +14 -14
  306. package/dist/server/errors-envelope.js +3 -3
  307. package/dist/session-transcript-DOM3UTXR.cjs +50 -0
  308. package/dist/{session-transcript-TNAJ4O3M.cjs.map → session-transcript-DOM3UTXR.cjs.map} +1 -1
  309. package/dist/session-transcript-RAKEK76V.js +5 -0
  310. package/dist/{session-transcript-SKIRBEJE.js.map → session-transcript-RAKEK76V.js.map} +1 -1
  311. package/dist/skills.cjs +7 -7
  312. package/dist/skills.js +5 -5
  313. package/dist/stream-object-L3Q7PBMF.cjs +20 -0
  314. package/dist/{stream-object-T4DAMNVB.cjs.map → stream-object-L3Q7PBMF.cjs.map} +1 -1
  315. package/dist/stream-object-ZYXWS4B2.js +7 -0
  316. package/dist/{stream-object-QMNR3YFF.js.map → stream-object-ZYXWS4B2.js.map} +1 -1
  317. package/dist/subagents-loader-I56GSKAQ.js +6 -0
  318. package/dist/{subagents-loader-WN2SB6PV.js.map → subagents-loader-I56GSKAQ.js.map} +1 -1
  319. package/dist/subagents-loader-VRW73QQT.cjs +15 -0
  320. package/dist/{subagents-loader-3CXBQWWY.cjs.map → subagents-loader-VRW73QQT.cjs.map} +1 -1
  321. package/dist/subagents-loader.cjs +6 -6
  322. package/dist/subagents-loader.d.cts +1 -1
  323. package/dist/subagents-loader.d.ts +1 -1
  324. package/dist/subagents-loader.js +4 -4
  325. package/dist/subscription/index.cjs +3 -3
  326. package/dist/subscription/index.js +2 -2
  327. package/dist/task-store.cjs +7 -7
  328. package/dist/task-store.js +4 -4
  329. package/dist/types/agent.d.ts +19 -6
  330. package/dist/types/provider-profile.d.ts +2 -2
  331. package/dist/workflow.cjs +27 -27
  332. package/dist/workflow.js +6 -6
  333. package/package.json +28 -18
  334. package/dist/agent-RDHK6MVT.js +0 -49
  335. package/dist/agent-U2R2R5JP.cjs +0 -58
  336. package/dist/agent-session-store-EPX2WQI4.cjs +0 -23
  337. package/dist/agent-session-store-JMU7ASDB.js +0 -6
  338. package/dist/chunk-2CFEET3Y.cjs.map +0 -1
  339. package/dist/chunk-2YGIBOUH.cjs.map +0 -1
  340. package/dist/chunk-4X3SBHPK.js.map +0 -1
  341. package/dist/chunk-6GS7JI64.cjs.map +0 -1
  342. package/dist/chunk-7HQVDLFI.cjs.map +0 -1
  343. package/dist/chunk-AM2CNBKE.js.map +0 -1
  344. package/dist/chunk-BBZYXVLZ.cjs.map +0 -1
  345. package/dist/chunk-BKRTYDVN.js +0 -312
  346. package/dist/chunk-BKRTYDVN.js.map +0 -1
  347. package/dist/chunk-CHVSMEKM.js.map +0 -1
  348. package/dist/chunk-GNPI5IWZ.js.map +0 -1
  349. package/dist/chunk-HI4ZW62S.js.map +0 -1
  350. package/dist/chunk-JJZ4NIAG.js.map +0 -1
  351. package/dist/chunk-KELIQH7K.js.map +0 -1
  352. package/dist/chunk-NACDF3PK.js.map +0 -1
  353. package/dist/chunk-QLAWEGTZ.cjs.map +0 -1
  354. package/dist/chunk-SDJYLCJK.cjs.map +0 -1
  355. package/dist/chunk-SXSPMRSV.cjs.map +0 -1
  356. package/dist/chunk-T6ZCG5AP.cjs.map +0 -1
  357. package/dist/chunk-V2EJLKGA.js.map +0 -1
  358. package/dist/chunk-W4FV7JBH.js.map +0 -1
  359. package/dist/chunk-XK54DTRF.cjs +0 -325
  360. package/dist/chunk-XK54DTRF.cjs.map +0 -1
  361. package/dist/chunk-XWCTBGYK.js.map +0 -1
  362. package/dist/chunk-YTO5BRBD.cjs.map +0 -1
  363. package/dist/chunk-ZNEE4WWQ.cjs.map +0 -1
  364. package/dist/compact-session-FBVWO6B3.cjs +0 -57
  365. package/dist/compact-session-XLXC2CZN.js +0 -20
  366. package/dist/context-4HGPCOH6.cjs +0 -22
  367. package/dist/context-DCECDKWN.js +0 -5
  368. package/dist/fs-session-store-2TF3ZWMT.js +0 -10
  369. package/dist/fs-session-store-TL4RJTXZ.cjs +0 -19
  370. package/dist/generate-object-E465DX5I.cjs +0 -20
  371. package/dist/generate-object-TVQCW2IZ.js +0 -7
  372. package/dist/index-manager-EA6FGIQG.js +0 -12
  373. package/dist/index-manager-HGGL4DD5.cjs +0 -21
  374. package/dist/judge-call-GVIJWQVE.cjs +0 -22
  375. package/dist/judge-call-QMKGC2ZK.js +0 -5
  376. package/dist/registry-GC7BQMSV.js +0 -9
  377. package/dist/registry-UBY26R4I.cjs +0 -46
  378. package/dist/session-transcript-SKIRBEJE.js +0 -5
  379. package/dist/session-transcript-TNAJ4O3M.cjs +0 -50
  380. package/dist/stream-object-QMNR3YFF.js +0 -7
  381. package/dist/stream-object-T4DAMNVB.cjs +0 -20
  382. package/dist/subagents-loader-3CXBQWWY.cjs +0 -15
  383. package/dist/subagents-loader-WN2SB6PV.js +0 -6
  384. package/docs/error-codes.md +0 -179
  385. package/docs/harness-capability-map.md +0 -304
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk2CFEET3Y_cjs = require('./chunk-2CFEET3Y.cjs');
4
- var chunkSXSPMRSV_cjs = require('./chunk-SXSPMRSV.cjs');
3
+ var chunkC4H6PB5J_cjs = require('./chunk-C4H6PB5J.cjs');
4
+ var chunkBM6N4KHO_cjs = require('./chunk-BM6N4KHO.cjs');
5
5
  var crypto = require('crypto');
6
6
  var promises = require('fs/promises');
7
7
  var os = require('os');
@@ -13,12 +13,12 @@ function encodeProjectDir(cwd) {
13
13
  function safeSessionId(id) {
14
14
  return id.replace(/[^a-zA-Z0-9_-]/g, "-");
15
15
  }
16
- var red = (s) => chunkSXSPMRSV_cjs.redactSecrets(s);
16
+ var red = (s) => chunkBM6N4KHO_cjs.redactSecrets(s);
17
17
  function redactValue(value) {
18
18
  try {
19
- return JSON.parse(chunkSXSPMRSV_cjs.redactSecrets(JSON.stringify(value ?? null)));
19
+ return JSON.parse(chunkBM6N4KHO_cjs.redactSecrets(JSON.stringify(value ?? null)));
20
20
  } catch {
21
- return chunkSXSPMRSV_cjs.redactSecrets(String(value));
21
+ return chunkBM6N4KHO_cjs.redactSecrets(String(value));
22
22
  }
23
23
  }
24
24
  var SessionTranscript = class _SessionTranscript {
@@ -223,7 +223,7 @@ function transcriptPath(baseDir, cwd, sessionId) {
223
223
  async function writeTranscript(path$1, records) {
224
224
  await promises.mkdir(path.dirname(path$1), { recursive: true });
225
225
  const body = records.map((r) => JSON.stringify(r)).join("\n");
226
- await chunk2CFEET3Y_cjs.replaceFileAtomic(path$1, records.length > 0 ? `${body}
226
+ await chunkC4H6PB5J_cjs.replaceFileAtomic(path$1, records.length > 0 ? `${body}
227
227
  ` : "");
228
228
  return path$1;
229
229
  }
@@ -258,5 +258,5 @@ exports.safeSessionId = safeSessionId;
258
258
  exports.transcriptPath = transcriptPath;
259
259
  exports.transcriptRoot = transcriptRoot;
260
260
  exports.writeTranscript = writeTranscript;
261
- //# sourceMappingURL=chunk-ECPL5RV6.cjs.map
262
- //# sourceMappingURL=chunk-ECPL5RV6.cjs.map
261
+ //# sourceMappingURL=chunk-Y4AXQOT4.cjs.map
262
+ //# sourceMappingURL=chunk-Y4AXQOT4.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/internal/persistence/session-transcript.ts"],"names":["redactSecrets","randomUUID","join","homedir","path","mkdir","dirname","replaceFileAtomic","readFile"],"mappings":"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","file":"chunk-ECPL5RV6.cjs","sourcesContent":["/**\n * SE40 — native session transcript (Claude-Code-compatible on-disk shape, theokit-native names).\n *\n * The theokit session format IS the Claude Code record shape (a `uuid`/`parentUuid` DAG of records with\n * structured `text`/`tool_use`/`tool_result`/`thinking` blocks) — so the ecosystem's read-side tools\n * parse our sessions AND, pointed at `~/.claude`, the Claude Code CLI can `--continue` them. This module\n * is the PURE core: append-per-turn record builders + the DAG reader that rebuilds `LlmMessage[]` for\n * resume. File I/O + loop wiring + append-only compaction live in the FS store.\n *\n * Reader mirrors `claude-code-log` dag.py: leaf = a uuid never used as a parentUuid; walk parentUuid to a\n * root (cycle-break); dedup a uuid across sessions keeping the earliest; a `compact_boundary` root\n * terminates the walk so a resume-after-compaction replays only the post-boundary continuation.\n *\n * reference: knowledge-base/references/claude-code-log/claude_code_log/dag.py + models.py\n */\nimport { randomUUID } from \"node:crypto\";\nimport { mkdir, readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport type { SessionRecord, TranscriptBlock } from \"../../types/session-record.js\";\nimport type { LlmContentPart, LlmMessage, LlmToolResultPart } from \"../llm/types.js\";\nimport { redactSecrets } from \"../security/redact.js\";\nimport { replaceFileAtomic } from \"./atomic-write.js\";\n\n// The `SessionRecord` contract now lives in the domain `types/` layer (SE46 DIP\n// direction). Re-exported here so existing importers of this DAG-core module\n// keep resolving the same name.\nexport type { SessionRecord } from \"../../types/session-record.js\";\n\nexport interface SessionTranscriptOptions {\n cwd: string;\n sessionId: string;\n model: string;\n version?: string;\n}\n\nexport interface AssistantTurn {\n text?: string;\n thinking?: string;\n /**\n * theokit#122 — the provider's signature for the thinking block. Written into the `thinking`\n * record block (`Block` already declared `signature?`), so a resumed session can replay the block\n * exactly as the provider issued it.\n */\n thinkingSignature?: string;\n toolCalls?: Array<{ id: string; name: string; input: Record<string, unknown> }>;\n}\n\n/** Claude Code path convention: cwd with every non-alphanumeric replaced by `-`. */\nexport function encodeProjectDir(cwd: string): string {\n return cwd.replace(/[^a-zA-Z0-9]/g, \"-\");\n}\n\n/** Make a caller-supplied session id safe as a path component (no traversal). */\nexport function safeSessionId(id: string): string {\n return id.replace(/[^a-zA-Z0-9_-]/g, \"-\");\n}\n\nconst red = (s: string): string => redactSecrets(s);\n\n/** Deep-redact a structured value (tool input) preserving object shape. */\nfunction redactValue(value: unknown): unknown {\n try {\n return JSON.parse(redactSecrets(JSON.stringify(value ?? null)));\n } catch {\n return redactSecrets(String(value));\n }\n}\n\n// M94 — it was `Record<string, unknown>`. The published type describes the same shape this file\n// has always produced; the local alias now points at it so writer and reader cannot\n// diverge silently.\ntype Block = TranscriptBlock;\n\n/**\n * Builds a session transcript append-by-append, maintaining the `parentUuid` chain. Each turn mints a\n * fresh `uuid` and parents on the previous record; `appendCompactBoundary` starts a NEW ROOT.\n */\nexport class SessionTranscript {\n #records: SessionRecord[] = [];\n #last: string | null = null;\n #opts: SessionTranscriptOptions;\n\n constructor(opts: SessionTranscriptOptions) {\n this.#opts = opts;\n }\n\n /**\n * Seed a transcript from records already on disk so a subsequent append parents\n * on the existing DAG leaf (the last record in file order). Prior records are\n * re-emitted verbatim by {@link records}, so the whole file rewrites atomically\n * as one append-only line set — never shrinking (SE40 compaction is append-only).\n */\n static fromRecords(\n prior: readonly SessionRecord[],\n opts: SessionTranscriptOptions,\n ): SessionTranscript {\n const t = new SessionTranscript(opts);\n t.#records = [...prior];\n t.#last = prior.length > 0 ? (prior[prior.length - 1]?.uuid ?? null) : null;\n return t;\n }\n\n #push(\n rec: Omit<SessionRecord, \"uuid\" | \"parentUuid\" | \"sessionId\" | \"timestamp\">,\n ): SessionRecord {\n const full: SessionRecord = {\n ...rec,\n uuid: randomUUID(),\n parentUuid: this.#last,\n sessionId: this.#opts.sessionId,\n timestamp: new Date().toISOString(),\n isSidechain: false,\n userType: \"external\",\n cwd: this.#opts.cwd,\n version: this.#opts.version ?? \"1.0.0-theokit\",\n };\n this.#records.push(full);\n this.#last = full.uuid;\n return full;\n }\n\n appendUserTurn(text: string): SessionRecord {\n return this.#push({\n type: \"user\",\n message: { role: \"user\", content: [{ type: \"text\", text: red(text) }] },\n });\n }\n\n appendAssistantTurn(turn: AssistantTurn): SessionRecord {\n const content: Block[] = [];\n if (turn.thinking) {\n // theokit#122 — the signature is computed by the provider over the ORIGINAL text, so it is\n // only valid while the text is byte-identical. Redaction rewrites the text; keeping the\n // signature next to a masked body persists a pair that Anthropic rejects with\n // `400 \"thinking blocks cannot be modified\"` — the very failure this issue exists to remove.\n //\n // So redaction WINS and the signature is dropped. The block survives as display-only history\n // (`thinkingToWireBlock` already refuses to replay an unsigned block), which loses one block\n // of context; keeping a signature that cannot verify would lose the whole turn.\n //\n // The signature itself is never redacted — it is an opaque provider token with no user\n // content — but that was only half the reasoning the first version of this fix wrote down.\n const redactedThinking = red(turn.thinking);\n const signatureStillValid =\n turn.thinkingSignature !== undefined && redactedThinking === turn.thinking;\n content.push({\n type: \"thinking\",\n thinking: redactedThinking,\n ...(signatureStillValid ? { signature: turn.thinkingSignature } : {}),\n });\n }\n if (turn.text) content.push({ type: \"text\", text: red(turn.text) });\n for (const c of turn.toolCalls ?? []) {\n content.push({ type: \"tool_use\", id: c.id, name: c.name, input: redactValue(c.input) });\n }\n return this.#push({\n type: \"assistant\",\n message: {\n id: randomUUID(),\n type: \"message\",\n role: \"assistant\",\n model: this.#opts.model,\n content,\n },\n });\n }\n\n appendToolResults(\n results: Array<{ toolUseId: string; content: string; isError?: boolean }>,\n ): SessionRecord {\n const content: Block[] = results.map((r) => ({\n type: \"tool_result\",\n tool_use_id: r.toolUseId,\n content: red(r.content),\n is_error: r.isError === true,\n }));\n return this.#push({ type: \"user\", message: { role: \"user\", content } });\n }\n\n /** Append-only compaction: a `compact_boundary` system record becomes a NEW ROOT (parentUuid null). */\n appendCompactBoundary(meta: { preTokens: number; trigger: string }): SessionRecord {\n const rec: SessionRecord = {\n type: \"system\",\n uuid: randomUUID(),\n parentUuid: null,\n sessionId: this.#opts.sessionId,\n timestamp: new Date().toISOString(),\n subtype: \"compact_boundary\",\n compactMetadata: meta,\n isSidechain: false,\n userType: \"external\",\n cwd: this.#opts.cwd,\n version: this.#opts.version ?? \"1.0.0-theokit\",\n };\n this.#records.push(rec);\n this.#last = rec.uuid;\n return rec;\n }\n\n records(): readonly SessionRecord[] {\n return this.#records;\n }\n}\n\n// ─── Reader (DAG → LlmMessage[]) ──────────────────────────────────────────────────────────────────\n\n/** Earliest timestamp seen per session id. */\nfunction sessionFirstTimestamps(records: readonly SessionRecord[]): Map<string, string> {\n const first = new Map<string, string>();\n for (const r of records) {\n const cur = first.get(r.sessionId);\n if (cur === undefined || r.timestamp < cur) first.set(r.sessionId, r.timestamp);\n }\n return first;\n}\n\n/** Dedup a uuid across sessions: keep the record whose session's earliest timestamp is smallest. */\nfunction dedupByUuid(records: readonly SessionRecord[]): Map<string, SessionRecord> {\n const firstTs = sessionFirstTimestamps(records);\n const byUuid = new Map<string, SessionRecord>();\n for (const r of records) {\n const existing = byUuid.get(r.uuid);\n const wins =\n existing === undefined ||\n (firstTs.get(r.sessionId) ?? \"\") < (firstTs.get(existing.sessionId) ?? \"\");\n if (wins) byUuid.set(r.uuid, r);\n }\n return byUuid;\n}\n\n/**\n * Map one structured block to an `LlmContentPart`.\n *\n * theokit#122 — thinking blocks used to be DROPPED here, which is why an extended-thinking session\n * could not be resumed: the block never made it back into the replayed messages, so the provider saw\n * a conversation whose assistant turn had lost its thinking. They are now reconstructed with their\n * signature; the Anthropic wire re-serializes signed blocks and skips unsigned ones.\n */\nfunction thinkingBlockToPart(b: Extract<Block, { type: \"thinking\" }>): LlmContentPart {\n return {\n type: \"thinking\",\n text: String(b.thinking ?? \"\"),\n ...(b.signature !== undefined ? { signature: String(b.signature) } : {}),\n };\n}\n\nfunction blockToPart(b: Block): LlmContentPart | undefined {\n if (b.type === \"text\") return { type: \"text\", text: String(b.text ?? \"\") };\n if (b.type === \"thinking\") return thinkingBlockToPart(b);\n if (b.type === \"tool_use\") {\n return {\n type: \"tool_use\",\n id: String(b.id),\n name: String(b.name),\n input: (b.input as Record<string, unknown>) ?? {},\n };\n }\n if (b.type === \"tool_result\") {\n const tr: LlmToolResultPart = {\n type: \"tool_result\",\n toolUseId: String(b.tool_use_id),\n content: typeof b.content === \"string\" ? b.content : JSON.stringify(b.content),\n isError: b.is_error === true,\n };\n return tr;\n }\n return undefined;\n}\n\n/** Map one record to an LlmMessage; `undefined` for non-conversational (system) records. */\nfunction recordToMessage(rec: SessionRecord): LlmMessage | undefined {\n if (rec.type !== \"user\" && rec.type !== \"assistant\") return undefined;\n const blocks = rec.message?.content ?? [];\n const parts = blocks.map(blockToPart).filter((p): p is LlmContentPart => p !== undefined);\n return { role: rec.type, content: parts };\n}\n\n/** The most-recent leaf: the LAST record (in input order) whose uuid is never used as a parentUuid. */\nfunction findLatestLeaf(\n records: readonly SessionRecord[],\n byUuid: Map<string, SessionRecord>,\n parents: Set<string>,\n): SessionRecord | undefined {\n let leaf: SessionRecord | undefined;\n for (const r of records) {\n if (byUuid.get(r.uuid) === r && !parents.has(r.uuid)) leaf = r;\n }\n return leaf;\n}\n\n/** Walk parentUuid from a leaf to a root (cycle-safe), returning root→leaf order. */\nfunction walkToRoot(leaf: SessionRecord, byUuid: Map<string, SessionRecord>): SessionRecord[] {\n const chain: SessionRecord[] = [];\n const seen = new Set<string>();\n let cur: SessionRecord | undefined = leaf;\n while (cur !== undefined && !seen.has(cur.uuid)) {\n seen.add(cur.uuid);\n chain.push(cur);\n cur = cur.parentUuid !== null ? byUuid.get(cur.parentUuid) : undefined;\n }\n return chain.reverse();\n}\n\n/**\n * Rebuild the resumable `LlmMessage[]` from transcript records: dedup → find the most-recent leaf →\n * walk `parentUuid` to a root (a `compact_boundary` root terminates the walk) → map to LlmMessages.\n * Returns them in root→leaf (chronological replay) order.\n */\nexport function reconstructMessages(records: readonly SessionRecord[]): LlmMessage[] {\n const byUuid = dedupByUuid(records);\n const parents = new Set<string>();\n for (const r of byUuid.values()) if (r.parentUuid) parents.add(r.parentUuid);\n const leaf = findLatestLeaf(records, byUuid, parents);\n if (leaf === undefined) return [];\n\n const msgs: LlmMessage[] = [];\n for (const rec of walkToRoot(leaf, byUuid)) {\n const m = recordToMessage(rec);\n if (m !== undefined) msgs.push(m);\n }\n return msgs;\n}\n\n// ─── File I/O (the on-disk Claude layout) ─────────────────────────────────────────────────────────\n\n/**\n * Root of the transcript state.\n *\n * `THEOKIT_HOME` wins; the fallback is `~/.theokit`. Home-anchored on purpose, and NOT\n * `paths.ts`'s `getTheokitHome(cwd)`: that one falls back to `<cwd>/.theokit`, and switching\n * by it would move the transcript of everyone who does **not** set the variable. The sibling with the\n * right shape is `catalog-source-models-dev.ts` (M94 ADR-2).\n *\n * Before M94 this function ignored the env var, so whoever set it had their state split in\n * two silently — sessions stayed in `~/.theokit` while the rest of the SDK migrated.\n */\nexport function transcriptRoot(): string {\n const override = process.env.THEOKIT_HOME?.trim();\n if (override !== undefined && override.length > 0) return override;\n return join(homedir(), \".theokit\");\n}\n\n/** @deprecated Use {@link transcriptRoot}. Kept as an alias — same value. */\nexport function defaultBaseDir(): string {\n return transcriptRoot();\n}\n\n/**\n * Expand a leading `~` / `~/` to the user's home dir. `node:path` does NOT expand `~`, so a\n * `baseDir: \"~/.claude\"` (the documented Claude Code CLI interop path) would otherwise resolve to a\n * literal `./~/.claude` under cwd and the CLI would never find the session. Absolute or relative\n * paths without a leading tilde pass through untouched.\n */\nexport function expandTilde(p: string): string {\n if (p === \"~\") return homedir();\n if (p.startsWith(\"~/\")) return join(homedir(), p.slice(2));\n return p;\n}\n\n/** The `.jsonl` path for a session: `<baseDir>/projects/<encoded-cwd>/<safe-sessionId>.jsonl`. */\nexport function transcriptPath(baseDir: string, cwd: string, sessionId: string): string {\n return join(baseDir, \"projects\", encodeProjectDir(cwd), `${safeSessionId(sessionId)}.jsonl`);\n}\n\n/** Write records as one JSONL line each (atomic; parent dir created). Returns the path. */\nexport async function writeTranscript(\n path: string,\n records: readonly SessionRecord[],\n): Promise<string> {\n await mkdir(dirname(path), { recursive: true });\n const body = records.map((r) => JSON.stringify(r)).join(\"\\n\");\n await replaceFileAtomic(path, records.length > 0 ? `${body}\\n` : \"\");\n return path;\n}\n\n/** Parse one JSONL line to a record; `undefined` for blank/torn/invalid lines (skipped on read). */\nfunction parseRecordLine(line: string): SessionRecord | undefined {\n const trimmed = line.trim();\n if (trimmed.length === 0) return undefined;\n try {\n const rec = JSON.parse(trimmed) as SessionRecord;\n return typeof rec.uuid === \"string\" && typeof rec.type === \"string\" ? rec : undefined;\n } catch {\n return undefined; // a torn last line (crash mid-write) — the rest of the DAG still reconstructs\n }\n}\n\n/** Parse a transcript `.jsonl` into records; a missing file yields `[]`; malformed lines are skipped. */\nexport async function readTranscript(path: string): Promise<SessionRecord[]> {\n let raw: string;\n try {\n raw = await readFile(path, \"utf8\");\n } catch (cause) {\n if ((cause as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw cause;\n }\n return raw\n .split(\"\\n\")\n .map(parseRecordLine)\n .filter((r): r is SessionRecord => r !== undefined);\n}\n"]}
1
+ {"version":3,"sources":["../src/internal/persistence/session-transcript.ts"],"names":["redactSecrets","randomUUID","join","homedir","path","mkdir","dirname","replaceFileAtomic","readFile"],"mappings":"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","file":"chunk-Y4AXQOT4.cjs","sourcesContent":["/**\n * SE40 — native session transcript (Claude-Code-compatible on-disk shape, theokit-native names).\n *\n * The theokit session format IS the Claude Code record shape (a `uuid`/`parentUuid` DAG of records with\n * structured `text`/`tool_use`/`tool_result`/`thinking` blocks) — so the ecosystem's read-side tools\n * parse our sessions AND, pointed at `~/.claude`, the Claude Code CLI can `--continue` them. This module\n * is the PURE core: append-per-turn record builders + the DAG reader that rebuilds `LlmMessage[]` for\n * resume. File I/O + loop wiring + append-only compaction live in the FS store.\n *\n * Reader mirrors `claude-code-log` dag.py: leaf = a uuid never used as a parentUuid; walk parentUuid to a\n * root (cycle-break); dedup a uuid across sessions keeping the earliest; a `compact_boundary` root\n * terminates the walk so a resume-after-compaction replays only the post-boundary continuation.\n *\n * reference: knowledge-base/references/claude-code-log/claude_code_log/dag.py + models.py\n */\nimport { randomUUID } from \"node:crypto\";\nimport { mkdir, readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport type { SessionRecord, TranscriptBlock } from \"../../types/session-record.js\";\nimport type { LlmContentPart, LlmMessage, LlmToolResultPart } from \"../llm/types.js\";\nimport { redactSecrets } from \"../security/redact.js\";\nimport { replaceFileAtomic } from \"./atomic-write.js\";\n\n// The `SessionRecord` contract now lives in the domain `types/` layer (SE46 DIP\n// direction). Re-exported here so existing importers of this DAG-core module\n// keep resolving the same name.\nexport type { SessionRecord } from \"../../types/session-record.js\";\n\nexport interface SessionTranscriptOptions {\n cwd: string;\n sessionId: string;\n model: string;\n version?: string;\n}\n\nexport interface AssistantTurn {\n text?: string;\n thinking?: string;\n /**\n * theokit#122 — the provider's signature for the thinking block. Written into the `thinking`\n * record block (`Block` already declared `signature?`), so a resumed session can replay the block\n * exactly as the provider issued it.\n */\n thinkingSignature?: string;\n toolCalls?: Array<{ id: string; name: string; input: Record<string, unknown> }>;\n}\n\n/** Claude Code path convention: cwd with every non-alphanumeric replaced by `-`. */\nexport function encodeProjectDir(cwd: string): string {\n return cwd.replace(/[^a-zA-Z0-9]/g, \"-\");\n}\n\n/** Make a caller-supplied session id safe as a path component (no traversal). */\nexport function safeSessionId(id: string): string {\n return id.replace(/[^a-zA-Z0-9_-]/g, \"-\");\n}\n\nconst red = (s: string): string => redactSecrets(s);\n\n/** Deep-redact a structured value (tool input) preserving object shape. */\nfunction redactValue(value: unknown): unknown {\n try {\n return JSON.parse(redactSecrets(JSON.stringify(value ?? null)));\n } catch {\n return redactSecrets(String(value));\n }\n}\n\n// M94 — it was `Record<string, unknown>`. The published type describes the same shape this file\n// has always produced; the local alias now points at it so writer and reader cannot\n// diverge silently.\ntype Block = TranscriptBlock;\n\n/**\n * Builds a session transcript append-by-append, maintaining the `parentUuid` chain. Each turn mints a\n * fresh `uuid` and parents on the previous record; `appendCompactBoundary` starts a NEW ROOT.\n */\nexport class SessionTranscript {\n #records: SessionRecord[] = [];\n #last: string | null = null;\n #opts: SessionTranscriptOptions;\n\n constructor(opts: SessionTranscriptOptions) {\n this.#opts = opts;\n }\n\n /**\n * Seed a transcript from records already on disk so a subsequent append parents\n * on the existing DAG leaf (the last record in file order). Prior records are\n * re-emitted verbatim by {@link records}, so the whole file rewrites atomically\n * as one append-only line set — never shrinking (SE40 compaction is append-only).\n */\n static fromRecords(\n prior: readonly SessionRecord[],\n opts: SessionTranscriptOptions,\n ): SessionTranscript {\n const t = new SessionTranscript(opts);\n t.#records = [...prior];\n t.#last = prior.length > 0 ? (prior[prior.length - 1]?.uuid ?? null) : null;\n return t;\n }\n\n #push(\n rec: Omit<SessionRecord, \"uuid\" | \"parentUuid\" | \"sessionId\" | \"timestamp\">,\n ): SessionRecord {\n const full: SessionRecord = {\n ...rec,\n uuid: randomUUID(),\n parentUuid: this.#last,\n sessionId: this.#opts.sessionId,\n timestamp: new Date().toISOString(),\n isSidechain: false,\n userType: \"external\",\n cwd: this.#opts.cwd,\n version: this.#opts.version ?? \"1.0.0-theokit\",\n };\n this.#records.push(full);\n this.#last = full.uuid;\n return full;\n }\n\n appendUserTurn(text: string): SessionRecord {\n return this.#push({\n type: \"user\",\n message: { role: \"user\", content: [{ type: \"text\", text: red(text) }] },\n });\n }\n\n appendAssistantTurn(turn: AssistantTurn): SessionRecord {\n const content: Block[] = [];\n if (turn.thinking) {\n // theokit#122 — the signature is computed by the provider over the ORIGINAL text, so it is\n // only valid while the text is byte-identical. Redaction rewrites the text; keeping the\n // signature next to a masked body persists a pair that Anthropic rejects with\n // `400 \"thinking blocks cannot be modified\"` — the very failure this issue exists to remove.\n //\n // So redaction WINS and the signature is dropped. The block survives as display-only history\n // (`thinkingToWireBlock` already refuses to replay an unsigned block), which loses one block\n // of context; keeping a signature that cannot verify would lose the whole turn.\n //\n // The signature itself is never redacted — it is an opaque provider token with no user\n // content — but that was only half the reasoning the first version of this fix wrote down.\n const redactedThinking = red(turn.thinking);\n const signatureStillValid =\n turn.thinkingSignature !== undefined && redactedThinking === turn.thinking;\n content.push({\n type: \"thinking\",\n thinking: redactedThinking,\n ...(signatureStillValid ? { signature: turn.thinkingSignature } : {}),\n });\n }\n if (turn.text) content.push({ type: \"text\", text: red(turn.text) });\n for (const c of turn.toolCalls ?? []) {\n content.push({ type: \"tool_use\", id: c.id, name: c.name, input: redactValue(c.input) });\n }\n return this.#push({\n type: \"assistant\",\n message: {\n id: randomUUID(),\n type: \"message\",\n role: \"assistant\",\n model: this.#opts.model,\n content,\n },\n });\n }\n\n appendToolResults(\n results: Array<{ toolUseId: string; content: string; isError?: boolean }>,\n ): SessionRecord {\n const content: Block[] = results.map((r) => ({\n type: \"tool_result\",\n tool_use_id: r.toolUseId,\n content: red(r.content),\n is_error: r.isError === true,\n }));\n return this.#push({ type: \"user\", message: { role: \"user\", content } });\n }\n\n /** Append-only compaction: a `compact_boundary` system record becomes a NEW ROOT (parentUuid null). */\n appendCompactBoundary(meta: { preTokens: number; trigger: string }): SessionRecord {\n const rec: SessionRecord = {\n type: \"system\",\n uuid: randomUUID(),\n parentUuid: null,\n sessionId: this.#opts.sessionId,\n timestamp: new Date().toISOString(),\n subtype: \"compact_boundary\",\n compactMetadata: meta,\n isSidechain: false,\n userType: \"external\",\n cwd: this.#opts.cwd,\n version: this.#opts.version ?? \"1.0.0-theokit\",\n };\n this.#records.push(rec);\n this.#last = rec.uuid;\n return rec;\n }\n\n records(): readonly SessionRecord[] {\n return this.#records;\n }\n}\n\n// ─── Reader (DAG → LlmMessage[]) ──────────────────────────────────────────────────────────────────\n\n/** Earliest timestamp seen per session id. */\nfunction sessionFirstTimestamps(records: readonly SessionRecord[]): Map<string, string> {\n const first = new Map<string, string>();\n for (const r of records) {\n const cur = first.get(r.sessionId);\n if (cur === undefined || r.timestamp < cur) first.set(r.sessionId, r.timestamp);\n }\n return first;\n}\n\n/** Dedup a uuid across sessions: keep the record whose session's earliest timestamp is smallest. */\nfunction dedupByUuid(records: readonly SessionRecord[]): Map<string, SessionRecord> {\n const firstTs = sessionFirstTimestamps(records);\n const byUuid = new Map<string, SessionRecord>();\n for (const r of records) {\n const existing = byUuid.get(r.uuid);\n const wins =\n existing === undefined ||\n (firstTs.get(r.sessionId) ?? \"\") < (firstTs.get(existing.sessionId) ?? \"\");\n if (wins) byUuid.set(r.uuid, r);\n }\n return byUuid;\n}\n\n/**\n * Map one structured block to an `LlmContentPart`.\n *\n * theokit#122 — thinking blocks used to be DROPPED here, which is why an extended-thinking session\n * could not be resumed: the block never made it back into the replayed messages, so the provider saw\n * a conversation whose assistant turn had lost its thinking. They are now reconstructed with their\n * signature; the Anthropic wire re-serializes signed blocks and skips unsigned ones.\n */\nfunction thinkingBlockToPart(b: Extract<Block, { type: \"thinking\" }>): LlmContentPart {\n return {\n type: \"thinking\",\n text: String(b.thinking ?? \"\"),\n ...(b.signature !== undefined ? { signature: String(b.signature) } : {}),\n };\n}\n\nfunction blockToPart(b: Block): LlmContentPart | undefined {\n if (b.type === \"text\") return { type: \"text\", text: String(b.text ?? \"\") };\n if (b.type === \"thinking\") return thinkingBlockToPart(b);\n if (b.type === \"tool_use\") {\n return {\n type: \"tool_use\",\n id: String(b.id),\n name: String(b.name),\n input: (b.input as Record<string, unknown>) ?? {},\n };\n }\n if (b.type === \"tool_result\") {\n const tr: LlmToolResultPart = {\n type: \"tool_result\",\n toolUseId: String(b.tool_use_id),\n content: typeof b.content === \"string\" ? b.content : JSON.stringify(b.content),\n isError: b.is_error === true,\n };\n return tr;\n }\n return undefined;\n}\n\n/** Map one record to an LlmMessage; `undefined` for non-conversational (system) records. */\nfunction recordToMessage(rec: SessionRecord): LlmMessage | undefined {\n if (rec.type !== \"user\" && rec.type !== \"assistant\") return undefined;\n const blocks = rec.message?.content ?? [];\n const parts = blocks.map(blockToPart).filter((p): p is LlmContentPart => p !== undefined);\n return { role: rec.type, content: parts };\n}\n\n/** The most-recent leaf: the LAST record (in input order) whose uuid is never used as a parentUuid. */\nfunction findLatestLeaf(\n records: readonly SessionRecord[],\n byUuid: Map<string, SessionRecord>,\n parents: Set<string>,\n): SessionRecord | undefined {\n let leaf: SessionRecord | undefined;\n for (const r of records) {\n if (byUuid.get(r.uuid) === r && !parents.has(r.uuid)) leaf = r;\n }\n return leaf;\n}\n\n/** Walk parentUuid from a leaf to a root (cycle-safe), returning root→leaf order. */\nfunction walkToRoot(leaf: SessionRecord, byUuid: Map<string, SessionRecord>): SessionRecord[] {\n const chain: SessionRecord[] = [];\n const seen = new Set<string>();\n let cur: SessionRecord | undefined = leaf;\n while (cur !== undefined && !seen.has(cur.uuid)) {\n seen.add(cur.uuid);\n chain.push(cur);\n cur = cur.parentUuid !== null ? byUuid.get(cur.parentUuid) : undefined;\n }\n return chain.reverse();\n}\n\n/**\n * Rebuild the resumable `LlmMessage[]` from transcript records: dedup → find the most-recent leaf →\n * walk `parentUuid` to a root (a `compact_boundary` root terminates the walk) → map to LlmMessages.\n * Returns them in root→leaf (chronological replay) order.\n */\nexport function reconstructMessages(records: readonly SessionRecord[]): LlmMessage[] {\n const byUuid = dedupByUuid(records);\n const parents = new Set<string>();\n for (const r of byUuid.values()) if (r.parentUuid) parents.add(r.parentUuid);\n const leaf = findLatestLeaf(records, byUuid, parents);\n if (leaf === undefined) return [];\n\n const msgs: LlmMessage[] = [];\n for (const rec of walkToRoot(leaf, byUuid)) {\n const m = recordToMessage(rec);\n if (m !== undefined) msgs.push(m);\n }\n return msgs;\n}\n\n// ─── File I/O (the on-disk Claude layout) ─────────────────────────────────────────────────────────\n\n/**\n * Root of the transcript state.\n *\n * `THEOKIT_HOME` wins; the fallback is `~/.theokit`. Home-anchored on purpose, and NOT\n * `paths.ts`'s `getTheokitHome(cwd)`: that one falls back to `<cwd>/.theokit`, and switching\n * by it would move the transcript of everyone who does **not** set the variable. The sibling with the\n * right shape is `catalog-source-models-dev.ts` (M94 ADR-2).\n *\n * Before M94 this function ignored the env var, so whoever set it had their state split in\n * two silently — sessions stayed in `~/.theokit` while the rest of the SDK migrated.\n */\nexport function transcriptRoot(): string {\n const override = process.env.THEOKIT_HOME?.trim();\n if (override !== undefined && override.length > 0) return override;\n return join(homedir(), \".theokit\");\n}\n\n/** @deprecated Use {@link transcriptRoot}. Kept as an alias — same value. */\nexport function defaultBaseDir(): string {\n return transcriptRoot();\n}\n\n/**\n * Expand a leading `~` / `~/` to the user's home dir. `node:path` does NOT expand `~`, so a\n * `baseDir: \"~/.claude\"` (the documented Claude Code CLI interop path) would otherwise resolve to a\n * literal `./~/.claude` under cwd and the CLI would never find the session. Absolute or relative\n * paths without a leading tilde pass through untouched.\n */\nexport function expandTilde(p: string): string {\n if (p === \"~\") return homedir();\n if (p.startsWith(\"~/\")) return join(homedir(), p.slice(2));\n return p;\n}\n\n/** The `.jsonl` path for a session: `<baseDir>/projects/<encoded-cwd>/<safe-sessionId>.jsonl`. */\nexport function transcriptPath(baseDir: string, cwd: string, sessionId: string): string {\n return join(baseDir, \"projects\", encodeProjectDir(cwd), `${safeSessionId(sessionId)}.jsonl`);\n}\n\n/** Write records as one JSONL line each (atomic; parent dir created). Returns the path. */\nexport async function writeTranscript(\n path: string,\n records: readonly SessionRecord[],\n): Promise<string> {\n await mkdir(dirname(path), { recursive: true });\n const body = records.map((r) => JSON.stringify(r)).join(\"\\n\");\n await replaceFileAtomic(path, records.length > 0 ? `${body}\\n` : \"\");\n return path;\n}\n\n/** Parse one JSONL line to a record; `undefined` for blank/torn/invalid lines (skipped on read). */\nfunction parseRecordLine(line: string): SessionRecord | undefined {\n const trimmed = line.trim();\n if (trimmed.length === 0) return undefined;\n try {\n const rec = JSON.parse(trimmed) as SessionRecord;\n return typeof rec.uuid === \"string\" && typeof rec.type === \"string\" ? rec : undefined;\n } catch {\n return undefined; // a torn last line (crash mid-write) — the rest of the DAG still reconstructs\n }\n}\n\n/** Parse a transcript `.jsonl` into records; a missing file yields `[]`; malformed lines are skipped. */\nexport async function readTranscript(path: string): Promise<SessionRecord[]> {\n let raw: string;\n try {\n raw = await readFile(path, \"utf8\");\n } catch (cause) {\n if ((cause as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw cause;\n }\n return raw\n .split(\"\\n\")\n .map(parseRecordLine)\n .filter((r): r is SessionRecord => r !== undefined);\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { setupStructuredOutput, makeOutputTool, buildTransientAgentOptions, buildToolPrompt, extractUsage, disposeAndDeleteTransient } from './chunk-I732VEDW.js';
1
+ import { setupStructuredOutput, makeOutputTool, buildTransientAgentOptions, buildToolPrompt, extractUsage, disposeAndDeleteTransient } from './chunk-D24WJWN2.js';
2
2
 
3
3
  // src/stream-object.ts
4
4
  var StreamObjectError = class extends Error {
@@ -141,5 +141,5 @@ function bestEffortPartialParse(text, schema) {
141
141
  }
142
142
 
143
143
  export { StreamObjectError, streamObjectImpl };
144
- //# sourceMappingURL=chunk-E6T264NS.js.map
145
- //# sourceMappingURL=chunk-E6T264NS.js.map
144
+ //# sourceMappingURL=chunk-Y4I4EQFK.js.map
145
+ //# sourceMappingURL=chunk-Y4I4EQFK.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/stream-object.ts"],"names":[],"mappings":"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","file":"chunk-E6T264NS.js","sourcesContent":["import type { z as ZodNamespace, ZodType } from \"zod\";\n\nimport {\n buildToolPrompt,\n buildTransientAgentOptions,\n disposeAndDeleteTransient,\n extractUsage,\n makeOutputTool,\n setupStructuredOutput,\n} from \"./internal/structured-output-helpers.js\";\nimport type { AgentOptions, LocalOptions, ModelSelection, SDKAgent } from \"./types/agent.js\";\nimport type { ProviderRoutingSettings } from \"./types/providers.js\";\n\n/**\n * Options accepted by {@link Agent.streamObject}. Same shape as\n * `Agent.generateObject` with the addition that the result is an\n * `AsyncIterator<StreamObjectEvent<T>>` rather than a single Promise. See ADR D39.\n *\n * @public\n */\nexport interface StreamObjectOptions<T extends ZodType> {\n schema: T;\n prompt: string;\n systemPrompt?: string;\n /** SE8 — accepts a bare-string id shorthand or a {@link ModelSelection}. */\n model: string | ModelSelection;\n apiKey?: string;\n local: LocalOptions;\n maxRetries?: number;\n /**\n * Optional provider routing forwarded to the transient agent. Required when\n * `model.id` uses a prefix (e.g. `openai/gpt-4o-mini`) but the credential is\n * for a unified gateway (e.g. OpenRouter). Without this, the SDK infers\n * provider from the prefix and may fail with `provider_unresolved` even\n * when the right env key is set under a different provider name.\n */\n providers?: ProviderRoutingSettings;\n}\n\n/**\n * Recursive partial — `T` where every nested field becomes optional.\n *\n * @public\n */\nexport type DeepPartial<T> = T extends (infer U)[]\n ? Array<DeepPartial<U>>\n : T extends object\n ? { [K in keyof T]?: DeepPartial<T[K]> }\n : T;\n\n/**\n * Event emitted by {@link Agent.streamObject}. Discriminate on `type`.\n *\n * - `partial` events fire zero or more times with monotonically increasing\n * `attempt`, carrying best-effort schema-parsed snapshots of the model's\n * accumulating output.\n * - `complete` fires exactly once at the end, carrying the fully Zod-parsed\n * object alongside usage and finishReason — semantically identical to a\n * successful `Agent.generateObject()` return.\n *\n * @public\n */\nexport type StreamObjectEvent<T> =\n | { type: \"partial\"; partial: DeepPartial<T>; attempt: number }\n | {\n type: \"complete\";\n object: T;\n raw: unknown;\n usage: { inputTokens: number; outputTokens: number };\n finishReason: \"tool_use\" | \"error\";\n };\n\n/**\n * Error thrown by {@link Agent.streamObject} when the model refuses to call\n * the synthetic `output` tool or when all retries fail to produce a\n * schema-valid object. Same code taxonomy as `GenerateObjectError`.\n *\n * @public\n */\nexport class StreamObjectError extends Error {\n override readonly name = \"StreamObjectError\";\n readonly code: \"no_tool_call\" | \"parse_failed\";\n override readonly cause?: unknown;\n constructor(code: \"no_tool_call\" | \"parse_failed\", message: string, cause?: unknown) {\n super(message);\n this.code = code;\n if (cause !== undefined) this.cause = cause;\n }\n}\n\ninterface StreamObjectDeps {\n create: (options: AgentOptions) => Promise<SDKAgent>;\n delete: (agentId: string) => Promise<void>;\n}\n\n/**\n * Implementation of `Agent.streamObject` as an async generator. Mirrors the\n * synthetic-forced-tool pattern from `generate-object.ts` (ADR D33) with the\n * addition of intermediate `partial` events emitted from incremental parsing\n * of accumulating text deltas during the agent loop.\n *\n * @internal\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: streaming loop interleaves text-delta accumulation, partial-parse attempts, retries, and final dispose — splitting harms locality of the iterator contract.\nexport async function* streamObjectImpl<T extends ZodType>(\n options: StreamObjectOptions<T>,\n deps: StreamObjectDeps,\n): AsyncGenerator<StreamObjectEvent<ZodNamespace.infer<T>>, void, void> {\n const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(\n options.schema,\n options.maxRetries,\n );\n let capturedRaw: unknown;\n let lastUsage = initialUsage;\n\n const outputTool = makeOutputTool(jsonSchema, (input) => {\n // EC-6: first capture wins (parallel tool use in Claude 3.5+).\n if (capturedRaw === undefined) {\n capturedRaw = input;\n }\n return JSON.stringify({ ok: true });\n });\n\n const agentOptions: AgentOptions = buildTransientAgentOptions({\n model: options.model,\n local: options.local,\n outputTool,\n ...(options.systemPrompt !== undefined ? { systemPrompt: options.systemPrompt } : {}),\n ...(options.apiKey !== undefined ? { apiKey: options.apiKey } : {}),\n ...(options.providers !== undefined ? { providers: options.providers } : {}),\n });\n const agent = await deps.create(agentOptions);\n const userMessage = buildToolPrompt(options.prompt);\n\n try {\n let lastParseError: unknown;\n let attemptCounter = 0;\n\n for (let attempt = 0; attempt <= maxRetries; attempt += 1) {\n capturedRaw = undefined;\n const run = await agent.send(userMessage);\n\n // Buffer text deltas during streaming; try partial-parse on each.\n let textBuffer = \"\";\n for await (const msg of run.stream()) {\n if (msg.type === \"assistant\") {\n const newText = msg.message.content\n .filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n .map((c) => c.text)\n .join(\"\");\n if (newText.length > 0) {\n textBuffer += newText;\n const partial = bestEffortPartialParse(textBuffer, options.schema);\n if (partial !== undefined) {\n attemptCounter += 1;\n yield {\n type: \"partial\",\n partial: partial as DeepPartial<ZodNamespace.infer<T>>,\n attempt: attemptCounter,\n };\n }\n }\n }\n }\n const result = await run.wait();\n lastUsage = extractUsage(result);\n\n if (capturedRaw === undefined) {\n // EC: when the underlying run errored (e.g. provider_unresolved),\n // surface the original cause instead of the misleading \"model\n // returned text\" message — there was no model call at all.\n if (result.status === \"error\" && result.error !== undefined) {\n throw new StreamObjectError(\n \"no_tool_call\",\n `Agent run failed before the model could reply: ${result.error.message ?? \"unknown error\"} [${result.error.code ?? \"?\"}]`,\n result.error,\n );\n }\n if (attempt === maxRetries) {\n throw new StreamObjectError(\n \"no_tool_call\",\n \"The model returned text instead of calling the `output` tool.\",\n );\n }\n continue;\n }\n\n const parsed = options.schema.safeParse(capturedRaw);\n if (parsed.success) {\n yield {\n type: \"complete\",\n object: parsed.data,\n raw: capturedRaw,\n usage: lastUsage,\n finishReason: \"tool_use\",\n };\n return;\n }\n lastParseError = parsed.error;\n }\n\n throw new StreamObjectError(\n \"parse_failed\",\n \"Schema parse failed after all retries.\",\n lastParseError,\n );\n } finally {\n // EC-4: even if consumer calls iter.return() mid-stream, this finally\n // runs — transient agent is disposed AND removed from registry.\n await disposeAndDeleteTransient(agent, deps.delete);\n }\n}\n\n/**\n * Try to extract a partial JSON object from a possibly-incomplete text\n * buffer and parse it via the schema in lenient mode. Returns `undefined`\n * if nothing parseable is found yet.\n *\n * Strategy: find the first `{`, find the LAST balanced `}` (greedy), parse\n * the substring as JSON, then `safeParse` against `schema.partial()` if the\n * schema supports it, else against the original schema.\n *\n * @internal\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: stateful JSON-balancing scanner — string/brace/escape state must be co-located for the parser to remain correct.\nfunction bestEffortPartialParse<T extends ZodType>(text: string, schema: T): unknown | undefined {\n const start = text.indexOf(\"{\");\n if (start < 0) return undefined;\n // Find the longest balanced JSON object from `start`.\n let depth = 0;\n let inString = false;\n let isEscaped = false;\n let end = -1;\n for (let i = start; i < text.length; i += 1) {\n const ch = text[i];\n if (isEscaped) {\n isEscaped = false;\n continue;\n }\n if (ch === \"\\\\\" && inString) {\n isEscaped = true;\n continue;\n }\n if (ch === '\"') {\n inString = !inString;\n continue;\n }\n if (inString) continue;\n if (ch === \"{\") depth += 1;\n else if (ch === \"}\") {\n depth -= 1;\n if (depth === 0) end = i;\n }\n }\n if (end < 0) return undefined;\n const candidate = text.slice(start, end + 1);\n let parsed: unknown;\n try {\n parsed = JSON.parse(candidate);\n } catch {\n return undefined;\n }\n // Try schema.partial() if available (Zod objects support it); else fall\n // back to the original schema (loose match).\n const maybePartial = (schema as unknown as { partial?: () => ZodType }).partial;\n const looseSchema = typeof maybePartial === \"function\" ? maybePartial.call(schema) : schema;\n const result = looseSchema.safeParse(parsed);\n return result.success ? result.data : undefined;\n}\n"]}
1
+ {"version":3,"sources":["../src/stream-object.ts"],"names":[],"mappings":"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","file":"chunk-Y4I4EQFK.js","sourcesContent":["import type { z as ZodNamespace, ZodType } from \"zod\";\n\nimport {\n buildToolPrompt,\n buildTransientAgentOptions,\n disposeAndDeleteTransient,\n extractUsage,\n makeOutputTool,\n setupStructuredOutput,\n} from \"./internal/structured-output-helpers.js\";\nimport type { AgentOptions, LocalOptions, ModelSelection, SDKAgent } from \"./types/agent.js\";\nimport type { ProviderRoutingSettings } from \"./types/providers.js\";\n\n/**\n * Options accepted by {@link Agent.streamObject}. Same shape as\n * `Agent.generateObject` with the addition that the result is an\n * `AsyncIterator<StreamObjectEvent<T>>` rather than a single Promise. See ADR D39.\n *\n * @public\n */\nexport interface StreamObjectOptions<T extends ZodType> {\n schema: T;\n prompt: string;\n systemPrompt?: string;\n /** SE8 — accepts a bare-string id shorthand or a {@link ModelSelection}. */\n model: string | ModelSelection;\n apiKey?: string;\n local: LocalOptions;\n maxRetries?: number;\n /**\n * Optional provider routing forwarded to the transient agent. Required when\n * `model.id` uses a prefix (e.g. `openai/gpt-4o-mini`) but the credential is\n * for a unified gateway (e.g. OpenRouter). Without this, the SDK infers\n * provider from the prefix and may fail with `provider_unresolved` even\n * when the right env key is set under a different provider name.\n */\n providers?: ProviderRoutingSettings;\n}\n\n/**\n * Recursive partial — `T` where every nested field becomes optional.\n *\n * @public\n */\nexport type DeepPartial<T> = T extends (infer U)[]\n ? Array<DeepPartial<U>>\n : T extends object\n ? { [K in keyof T]?: DeepPartial<T[K]> }\n : T;\n\n/**\n * Event emitted by {@link Agent.streamObject}. Discriminate on `type`.\n *\n * - `partial` events fire zero or more times with monotonically increasing\n * `attempt`, carrying best-effort schema-parsed snapshots of the model's\n * accumulating output.\n * - `complete` fires exactly once at the end, carrying the fully Zod-parsed\n * object alongside usage and finishReason — semantically identical to a\n * successful `Agent.generateObject()` return.\n *\n * @public\n */\nexport type StreamObjectEvent<T> =\n | { type: \"partial\"; partial: DeepPartial<T>; attempt: number }\n | {\n type: \"complete\";\n object: T;\n raw: unknown;\n usage: { inputTokens: number; outputTokens: number };\n finishReason: \"tool_use\" | \"error\";\n };\n\n/**\n * Error thrown by {@link Agent.streamObject} when the model refuses to call\n * the synthetic `output` tool or when all retries fail to produce a\n * schema-valid object. Same code taxonomy as `GenerateObjectError`.\n *\n * @public\n */\nexport class StreamObjectError extends Error {\n override readonly name = \"StreamObjectError\";\n readonly code: \"no_tool_call\" | \"parse_failed\";\n override readonly cause?: unknown;\n constructor(code: \"no_tool_call\" | \"parse_failed\", message: string, cause?: unknown) {\n super(message);\n this.code = code;\n if (cause !== undefined) this.cause = cause;\n }\n}\n\ninterface StreamObjectDeps {\n create: (options: AgentOptions) => Promise<SDKAgent>;\n delete: (agentId: string) => Promise<void>;\n}\n\n/**\n * Implementation of `Agent.streamObject` as an async generator. Mirrors the\n * synthetic-forced-tool pattern from `generate-object.ts` (ADR D33) with the\n * addition of intermediate `partial` events emitted from incremental parsing\n * of accumulating text deltas during the agent loop.\n *\n * @internal\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: streaming loop interleaves text-delta accumulation, partial-parse attempts, retries, and final dispose — splitting harms locality of the iterator contract.\nexport async function* streamObjectImpl<T extends ZodType>(\n options: StreamObjectOptions<T>,\n deps: StreamObjectDeps,\n): AsyncGenerator<StreamObjectEvent<ZodNamespace.infer<T>>, void, void> {\n const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(\n options.schema,\n options.maxRetries,\n );\n let capturedRaw: unknown;\n let lastUsage = initialUsage;\n\n const outputTool = makeOutputTool(jsonSchema, (input) => {\n // EC-6: first capture wins (parallel tool use in Claude 3.5+).\n if (capturedRaw === undefined) {\n capturedRaw = input;\n }\n return JSON.stringify({ ok: true });\n });\n\n const agentOptions: AgentOptions = buildTransientAgentOptions({\n model: options.model,\n local: options.local,\n outputTool,\n ...(options.systemPrompt !== undefined ? { systemPrompt: options.systemPrompt } : {}),\n ...(options.apiKey !== undefined ? { apiKey: options.apiKey } : {}),\n ...(options.providers !== undefined ? { providers: options.providers } : {}),\n });\n const agent = await deps.create(agentOptions);\n const userMessage = buildToolPrompt(options.prompt);\n\n try {\n let lastParseError: unknown;\n let attemptCounter = 0;\n\n for (let attempt = 0; attempt <= maxRetries; attempt += 1) {\n capturedRaw = undefined;\n const run = await agent.send(userMessage);\n\n // Buffer text deltas during streaming; try partial-parse on each.\n let textBuffer = \"\";\n for await (const msg of run.stream()) {\n if (msg.type === \"assistant\") {\n const newText = msg.message.content\n .filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n .map((c) => c.text)\n .join(\"\");\n if (newText.length > 0) {\n textBuffer += newText;\n const partial = bestEffortPartialParse(textBuffer, options.schema);\n if (partial !== undefined) {\n attemptCounter += 1;\n yield {\n type: \"partial\",\n partial: partial as DeepPartial<ZodNamespace.infer<T>>,\n attempt: attemptCounter,\n };\n }\n }\n }\n }\n const result = await run.wait();\n lastUsage = extractUsage(result);\n\n if (capturedRaw === undefined) {\n // EC: when the underlying run errored (e.g. provider_unresolved),\n // surface the original cause instead of the misleading \"model\n // returned text\" message — there was no model call at all.\n if (result.status === \"error\" && result.error !== undefined) {\n throw new StreamObjectError(\n \"no_tool_call\",\n `Agent run failed before the model could reply: ${result.error.message ?? \"unknown error\"} [${result.error.code ?? \"?\"}]`,\n result.error,\n );\n }\n if (attempt === maxRetries) {\n throw new StreamObjectError(\n \"no_tool_call\",\n \"The model returned text instead of calling the `output` tool.\",\n );\n }\n continue;\n }\n\n const parsed = options.schema.safeParse(capturedRaw);\n if (parsed.success) {\n yield {\n type: \"complete\",\n object: parsed.data,\n raw: capturedRaw,\n usage: lastUsage,\n finishReason: \"tool_use\",\n };\n return;\n }\n lastParseError = parsed.error;\n }\n\n throw new StreamObjectError(\n \"parse_failed\",\n \"Schema parse failed after all retries.\",\n lastParseError,\n );\n } finally {\n // EC-4: even if consumer calls iter.return() mid-stream, this finally\n // runs — transient agent is disposed AND removed from registry.\n await disposeAndDeleteTransient(agent, deps.delete);\n }\n}\n\n/**\n * Try to extract a partial JSON object from a possibly-incomplete text\n * buffer and parse it via the schema in lenient mode. Returns `undefined`\n * if nothing parseable is found yet.\n *\n * Strategy: find the first `{`, find the LAST balanced `}` (greedy), parse\n * the substring as JSON, then `safeParse` against `schema.partial()` if the\n * schema supports it, else against the original schema.\n *\n * @internal\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: stateful JSON-balancing scanner — string/brace/escape state must be co-located for the parser to remain correct.\nfunction bestEffortPartialParse<T extends ZodType>(text: string, schema: T): unknown | undefined {\n const start = text.indexOf(\"{\");\n if (start < 0) return undefined;\n // Find the longest balanced JSON object from `start`.\n let depth = 0;\n let inString = false;\n let isEscaped = false;\n let end = -1;\n for (let i = start; i < text.length; i += 1) {\n const ch = text[i];\n if (isEscaped) {\n isEscaped = false;\n continue;\n }\n if (ch === \"\\\\\" && inString) {\n isEscaped = true;\n continue;\n }\n if (ch === '\"') {\n inString = !inString;\n continue;\n }\n if (inString) continue;\n if (ch === \"{\") depth += 1;\n else if (ch === \"}\") {\n depth -= 1;\n if (depth === 0) end = i;\n }\n }\n if (end < 0) return undefined;\n const candidate = text.slice(start, end + 1);\n let parsed: unknown;\n try {\n parsed = JSON.parse(candidate);\n } catch {\n return undefined;\n }\n // Try schema.partial() if available (Zod objects support it); else fall\n // back to the original schema (loose match).\n const maybePartial = (schema as unknown as { partial?: () => ZodType }).partial;\n const looseSchema = typeof maybePartial === \"function\" ? maybePartial.call(schema) : schema;\n const result = looseSchema.safeParse(parsed);\n return result.success ? result.data : undefined;\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunkYTO5BRBD_cjs = require('./chunk-YTO5BRBD.cjs');
4
- var chunk44IISBRZ_cjs = require('./chunk-44IISBRZ.cjs');
5
- var chunk2YGIBOUH_cjs = require('./chunk-2YGIBOUH.cjs');
3
+ var chunkZT57WTUJ_cjs = require('./chunk-ZT57WTUJ.cjs');
4
+ var chunkSZHU7A5B_cjs = require('./chunk-SZHU7A5B.cjs');
5
+ var chunkLPVIRJVF_cjs = require('./chunk-LPVIRJVF.cjs');
6
6
  var promises = require('fs/promises');
7
7
  var path = require('path');
8
8
 
@@ -28,16 +28,16 @@ function stripSkillFrontmatter(raw) {
28
28
  function extractAndParseFrontmatter(raw, fallbackName) {
29
29
  const match = /^---\s*\n([\s\S]*?)\n---\s*\n/.exec(raw);
30
30
  if (match === null) {
31
- throw new chunk2YGIBOUH_cjs.ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {
31
+ throw new chunkLPVIRJVF_cjs.ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {
32
32
  code: "missing_frontmatter"
33
33
  });
34
34
  }
35
35
  const frontmatter = match[1] ?? "";
36
36
  try {
37
- return toStringFields(chunk44IISBRZ_cjs.parseSimpleYaml(frontmatter));
37
+ return toStringFields(chunkSZHU7A5B_cjs.parseSimpleYaml(frontmatter));
38
38
  } catch (cause) {
39
39
  const detail = cause instanceof Error ? cause.message : String(cause);
40
- throw new chunk2YGIBOUH_cjs.ConfigurationError(
40
+ throw new chunkLPVIRJVF_cjs.ConfigurationError(
41
41
  `Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,
42
42
  { code: "schema_invalid", cause }
43
43
  );
@@ -46,13 +46,13 @@ function extractAndParseFrontmatter(raw, fallbackName) {
46
46
  function resolveName(fields, fallbackName) {
47
47
  if (hasContent(fields.name)) return fields.name;
48
48
  if (hasContent(fallbackName)) return fallbackName;
49
- throw new chunk2YGIBOUH_cjs.ConfigurationError("Skill at unknown path is missing required field: name", {
49
+ throw new chunkLPVIRJVF_cjs.ConfigurationError("Skill at unknown path is missing required field: name", {
50
50
  code: "schema_invalid"
51
51
  });
52
52
  }
53
53
  function ensureRequiredFields(fields, name) {
54
54
  if (!hasContent(fields.description)) {
55
- throw new chunk2YGIBOUH_cjs.ConfigurationError(`Skill ${name} is missing required field: description`, {
55
+ throw new chunkLPVIRJVF_cjs.ConfigurationError(`Skill ${name} is missing required field: description`, {
56
56
  code: "schema_invalid"
57
57
  });
58
58
  }
@@ -60,7 +60,7 @@ function ensureRequiredFields(fields, name) {
60
60
  function buildFrontmatter(fields, name) {
61
61
  const description = fields.description;
62
62
  if (description === void 0) {
63
- throw new chunk2YGIBOUH_cjs.ConfigurationError(`Skill ${name} missing description`, { code: "schema_invalid" });
63
+ throw new chunkLPVIRJVF_cjs.ConfigurationError(`Skill ${name} missing description`, { code: "schema_invalid" });
64
64
  }
65
65
  const result = { name, description };
66
66
  if (hasContent(fields.category)) result.category = fields.category;
@@ -81,7 +81,7 @@ function hasContent(value) {
81
81
  async function discoverSkills(dir, options) {
82
82
  let entries;
83
83
  try {
84
- entries = await chunk44IISBRZ_cjs.readWorkspaceDir(dir, "skills_read_error", "skills directory");
84
+ entries = await chunkSZHU7A5B_cjs.readWorkspaceDir(dir, "skills_read_error", "skills directory");
85
85
  } catch {
86
86
  return [];
87
87
  }
@@ -90,8 +90,8 @@ async function discoverSkills(dir, options) {
90
90
  if (!entry.isDirectory()) continue;
91
91
  let skillDir;
92
92
  try {
93
- skillDir = chunkYTO5BRBD_cjs.safePathJoin(dir, entry.name);
94
- chunkYTO5BRBD_cjs.assertNoSymlinkEscape(skillDir, dir);
93
+ skillDir = chunkZT57WTUJ_cjs.safePathJoin(dir, entry.name);
94
+ chunkZT57WTUJ_cjs.assertNoSymlinkEscape(skillDir, dir);
95
95
  } catch {
96
96
  continue;
97
97
  }
@@ -119,7 +119,7 @@ function tryParseSkill(raw, fallbackName, source, options) {
119
119
  if (frontmatter.dependencies !== void 0) skill.dependencies = frontmatter.dependencies;
120
120
  return skill;
121
121
  } catch (cause) {
122
- if (cause instanceof chunk2YGIBOUH_cjs.ConfigurationError) {
122
+ if (cause instanceof chunkLPVIRJVF_cjs.ConfigurationError) {
123
123
  options?.onInvalidSkill?.({
124
124
  name: fallbackName,
125
125
  source,
@@ -150,5 +150,5 @@ exports.buildSkillsBlock = buildSkillsBlock;
150
150
  exports.discoverSkills = discoverSkills;
151
151
  exports.escapeBlockBody = escapeBlockBody;
152
152
  exports.stripSkillFrontmatter = stripSkillFrontmatter;
153
- //# sourceMappingURL=chunk-FUASIT3E.cjs.map
154
- //# sourceMappingURL=chunk-FUASIT3E.cjs.map
153
+ //# sourceMappingURL=chunk-ZN2DGEY3.cjs.map
154
+ //# sourceMappingURL=chunk-ZN2DGEY3.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/internal/runtime/skills/skill-frontmatter.ts","../src/internal/runtime/skills/discover-skills.ts","../src/internal/runtime/system-prompt/escape.ts","../src/internal/runtime/skills/skills-block.ts"],"names":["ConfigurationError","parseSimpleYaml","readWorkspaceDir","safePathJoin","assertNoSymlinkEscape","join","readFile"],"mappings":"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","file":"chunk-FUASIT3E.cjs","sourcesContent":["import { ConfigurationError } from \"../../../errors.js\";\nimport { type FrontmatterValue, parseSimpleYaml } from \"../context/yaml-frontmatter.js\";\n\ntype StringFields = Record<string, string | undefined>;\n\n/** Narrow a FrontmatterValue to string; non-strings + undefined → undefined. */\nfunction asString(v: FrontmatterValue | undefined): string | undefined {\n return typeof v === \"string\" ? v : undefined;\n}\n\n/** Coerce parser output to legacy string-only shape (skill schema is all-string). */\nfunction toStringFields(raw: Record<string, FrontmatterValue | undefined>): StringFields {\n const out: StringFields = {};\n for (const [k, v] of Object.entries(raw)) out[k] = asString(v);\n return out;\n}\n\n/**\n * Strict skill frontmatter schema (ADR D10).\n *\n * Required: `name`, `description`.\n * Optional: `category`, `dependencies` (comma-separated string in the\n * simple-YAML dialect — parsed to `string[]`).\n *\n * Unknown fields are ignored (forward-compat). Malformed YAML or missing\n * required fields surface as `ConfigurationError` with one of the typed\n * codes below.\n *\n * @internal\n */\nexport interface SkillFrontmatter {\n name: string;\n description: string;\n category?: string;\n dependencies?: string[];\n}\n\n/**\n * Parse a SKILL.md file body into validated frontmatter.\n *\n * @throws ConfigurationError(code: \"missing_frontmatter\") — no `---` block at file head.\n * @throws ConfigurationError(code: \"schema_invalid\") — YAML malformed OR required field missing.\n *\n * @internal\n */\nexport function parseSkillFrontmatter(raw: string, fallbackName: string): SkillFrontmatter {\n const fields = extractAndParseFrontmatter(raw, fallbackName);\n const name = resolveName(fields, fallbackName);\n ensureRequiredFields(fields, name);\n return buildFrontmatter(fields, name);\n}\n\n/**\n * SE20 — return a SKILL.md's BODY (everything after the frontmatter block), trimmed.\n * When there is no frontmatter block, the whole file is the body. Reuses the same\n * frontmatter regex as {@link parseSkillFrontmatter} (DRY).\n */\nexport function stripSkillFrontmatter(raw: string): string {\n const match = /^---\\s*\\n[\\s\\S]*?\\n---\\s*\\n/.exec(raw);\n return (match === null ? raw : raw.slice(match[0].length)).trim();\n}\n\nfunction extractAndParseFrontmatter(raw: string, fallbackName: string): StringFields {\n const match = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n/.exec(raw);\n if (match === null) {\n throw new ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {\n code: \"missing_frontmatter\",\n });\n }\n const frontmatter = match[1] ?? \"\";\n // EC-5: guard against syntactically invalid frontmatter so the loader\n // surfaces schema_invalid rather than crashing.\n try {\n return toStringFields(parseSimpleYaml(frontmatter));\n } catch (cause) {\n const detail = cause instanceof Error ? cause.message : String(cause);\n throw new ConfigurationError(\n `Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,\n { code: \"schema_invalid\", cause },\n );\n }\n}\n\nfunction resolveName(fields: StringFields, fallbackName: string): string {\n if (hasContent(fields.name)) return fields.name;\n if (hasContent(fallbackName)) return fallbackName;\n throw new ConfigurationError(\"Skill at unknown path is missing required field: name\", {\n code: \"schema_invalid\",\n });\n}\n\nfunction ensureRequiredFields(fields: StringFields, name: string): void {\n if (!hasContent(fields.description)) {\n throw new ConfigurationError(`Skill ${name} is missing required field: description`, {\n code: \"schema_invalid\",\n });\n }\n}\n\nfunction buildFrontmatter(fields: StringFields, name: string): SkillFrontmatter {\n const description = fields.description;\n if (description === undefined) {\n // ensureRequiredFields already threw; this is unreachable but satisfies TS\n throw new ConfigurationError(`Skill ${name} missing description`, { code: \"schema_invalid\" });\n }\n const result: SkillFrontmatter = { name, description };\n if (hasContent(fields.category)) result.category = fields.category;\n const deps = parseDependencies(fields.dependencies);\n if (deps !== undefined) result.dependencies = deps;\n return result;\n}\n\nfunction parseDependencies(raw: string | undefined): string[] | undefined {\n if (!hasContent(raw)) return undefined;\n const deps = (raw as string)\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n return deps.length > 0 ? deps : undefined;\n}\n\nfunction hasContent(value: string | undefined): value is string {\n return value !== undefined && value.trim().length > 0;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { ConfigurationError } from \"../../../errors.js\";\nimport { assertNoSymlinkEscape, safePathJoin } from \"../../security/path-guard.js\";\nimport { readWorkspaceDir } from \"../config/workspace-dir.js\";\nimport { parseSkillFrontmatter } from \"./skill-frontmatter.js\";\n\n/**\n * A discovered skill's metadata. The skill BODY is never included — only the\n * strict frontmatter fields plus the resolved `source` path.\n *\n * Public via `@theokit/sdk/skills`.\n *\n * @public\n */\nexport interface Skill {\n name: string;\n description: string;\n /** Absolute path to the discovered `SKILL.md`. */\n source: string;\n category?: string;\n dependencies?: string[];\n}\n\n/**\n * Information passed to `onInvalidSkill` when a `SKILL.md` is present but its\n * frontmatter is malformed (missing required field or invalid YAML).\n *\n * @public\n */\nexport interface InvalidSkillInfo {\n /** The skill directory name (used as the fallback skill name). */\n name: string;\n /** Absolute path to the offending `SKILL.md`. */\n source: string;\n /** Typed reason: `missing_frontmatter` or `schema_invalid`. */\n code: string;\n message: string;\n}\n\n/**\n * Options for {@link discoverSkills}.\n *\n * @public\n */\nexport interface DiscoverSkillsOptions {\n /**\n * Called once per directory that contains a `SKILL.md` with malformed\n * frontmatter. The skill is excluded from the result; discovery continues\n * (strict-frontmatter ADR / EC-5). A directory WITHOUT a `SKILL.md` is NOT a\n * malformed skill and does not trigger this callback.\n *\n * Default: no-op (a library primitive must not write to the consumer's\n * stderr by default).\n */\n onInvalidSkill?: (info: InvalidSkillInfo) => void;\n}\n\n/**\n * Discover `SKILL.md` skills under an arbitrary directory.\n *\n * For each immediate subdirectory `<dir>/<name>/` containing a `SKILL.md`, the\n * file's strict YAML frontmatter is parsed (`name`/`description` required;\n * `category`/`dependencies` optional). Malformed skills are skipped (optionally\n * reported via {@link DiscoverSkillsOptions.onInvalidSkill}); a subdirectory\n * whose realpath escapes `dir` (via symlink) is skipped (symlink-escape guard,\n * reusing `@theokit/sdk/path-safety`).\n *\n * NEVER throws: a missing, unreadable, or non-directory `dir` yields `[]`.\n *\n * Discovery order follows the filesystem `readdir` order (OS-dependent). Sort\n * the result before {@link buildSkillsBlock} if a stable block order matters.\n *\n * Public via `@theokit/sdk/skills`.\n *\n * @public\n */\nexport async function discoverSkills(\n dir: string,\n options?: DiscoverSkillsOptions,\n): Promise<Skill[]> {\n let entries: Awaited<ReturnType<typeof readWorkspaceDir>>;\n try {\n entries = await readWorkspaceDir(dir, \"skills_read_error\", \"skills directory\");\n } catch {\n // never-throw contract: unreadable / not-a-directory → no skills (EC-1)\n return [];\n }\n\n const skills: Skill[] = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n let skillDir: string;\n try {\n skillDir = safePathJoin(dir, entry.name);\n assertNoSymlinkEscape(skillDir, dir);\n } catch {\n continue;\n }\n const skillPath = join(skillDir, \"SKILL.md\");\n let raw: string;\n try {\n raw = await readFile(skillPath, \"utf8\");\n } catch {\n // no SKILL.md in this subdir → not a skill, not an error (EC-2)\n continue;\n }\n const skill = tryParseSkill(raw, entry.name, skillPath, options);\n if (skill !== undefined) skills.push(skill);\n }\n return skills;\n}\n\nfunction tryParseSkill(\n raw: string,\n fallbackName: string,\n source: string,\n options: DiscoverSkillsOptions | undefined,\n): Skill | undefined {\n try {\n const frontmatter = parseSkillFrontmatter(raw, fallbackName);\n const skill: Skill = {\n name: frontmatter.name,\n description: frontmatter.description,\n source,\n };\n if (frontmatter.category !== undefined) skill.category = frontmatter.category;\n if (frontmatter.dependencies !== undefined) skill.dependencies = frontmatter.dependencies;\n return skill;\n } catch (cause) {\n if (cause instanceof ConfigurationError) {\n options?.onInvalidSkill?.({\n name: fallbackName,\n source,\n code: cause.code ?? \"unknown\",\n message: cause.message,\n });\n return undefined;\n }\n throw cause;\n }\n}\n","/**\n * Block-body XML escape (ADR D9 — prompt-injection defence).\n *\n * Order matters: `&` MUST be escaped first so subsequent `<`/`>` replacements\n * do not double-encode the `&` characters they introduce.\n *\n * @internal\n */\nexport const escapeBlockBody = (s: string): string =>\n s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n","import { escapeBlockBody } from \"../system-prompt/escape.js\";\n\n/**\n * Render the `<skills>` system-prompt block from a skill list.\n *\n * Input is the structural subset `{ name, description }` — the skill BODY is\n * NOT in the type, so it cannot leak into the prompt. Both fields are passed\n * through `escapeBlockBody` to neutralise prompt-injection vectors hidden in\n * user-controlled SKILL.md frontmatter (injection-escape ADR).\n *\n * Returns `undefined` for an empty list so the caller can omit the block.\n *\n * Public via `@theokit/sdk/skills`.\n *\n * @public\n */\nexport function buildSkillsBlock(\n skills: ReadonlyArray<{ name: string; description: string }>,\n): string | undefined {\n if (skills.length === 0) return undefined;\n const lines = skills.map(\n (skill) => ` - ${escapeBlockBody(skill.name)}: ${escapeBlockBody(skill.description)}`,\n );\n return `<skills>\\n${lines.join(\"\\n\")}\\n</skills>`;\n}\n"]}
1
+ {"version":3,"sources":["../src/internal/runtime/skills/skill-frontmatter.ts","../src/internal/runtime/skills/discover-skills.ts","../src/internal/runtime/system-prompt/escape.ts","../src/internal/runtime/skills/skills-block.ts"],"names":["ConfigurationError","parseSimpleYaml","readWorkspaceDir","safePathJoin","assertNoSymlinkEscape","join","readFile"],"mappings":"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","file":"chunk-ZN2DGEY3.cjs","sourcesContent":["import { ConfigurationError } from \"../../../errors.js\";\nimport { type FrontmatterValue, parseSimpleYaml } from \"../context/yaml-frontmatter.js\";\n\ntype StringFields = Record<string, string | undefined>;\n\n/** Narrow a FrontmatterValue to string; non-strings + undefined → undefined. */\nfunction asString(v: FrontmatterValue | undefined): string | undefined {\n return typeof v === \"string\" ? v : undefined;\n}\n\n/** Coerce parser output to legacy string-only shape (skill schema is all-string). */\nfunction toStringFields(raw: Record<string, FrontmatterValue | undefined>): StringFields {\n const out: StringFields = {};\n for (const [k, v] of Object.entries(raw)) out[k] = asString(v);\n return out;\n}\n\n/**\n * Strict skill frontmatter schema (ADR D10).\n *\n * Required: `name`, `description`.\n * Optional: `category`, `dependencies` (comma-separated string in the\n * simple-YAML dialect — parsed to `string[]`).\n *\n * Unknown fields are ignored (forward-compat). Malformed YAML or missing\n * required fields surface as `ConfigurationError` with one of the typed\n * codes below.\n *\n * @internal\n */\nexport interface SkillFrontmatter {\n name: string;\n description: string;\n category?: string;\n dependencies?: string[];\n}\n\n/**\n * Parse a SKILL.md file body into validated frontmatter.\n *\n * @throws ConfigurationError(code: \"missing_frontmatter\") — no `---` block at file head.\n * @throws ConfigurationError(code: \"schema_invalid\") — YAML malformed OR required field missing.\n *\n * @internal\n */\nexport function parseSkillFrontmatter(raw: string, fallbackName: string): SkillFrontmatter {\n const fields = extractAndParseFrontmatter(raw, fallbackName);\n const name = resolveName(fields, fallbackName);\n ensureRequiredFields(fields, name);\n return buildFrontmatter(fields, name);\n}\n\n/**\n * SE20 — return a SKILL.md's BODY (everything after the frontmatter block), trimmed.\n * When there is no frontmatter block, the whole file is the body. Reuses the same\n * frontmatter regex as {@link parseSkillFrontmatter} (DRY).\n */\nexport function stripSkillFrontmatter(raw: string): string {\n const match = /^---\\s*\\n[\\s\\S]*?\\n---\\s*\\n/.exec(raw);\n return (match === null ? raw : raw.slice(match[0].length)).trim();\n}\n\nfunction extractAndParseFrontmatter(raw: string, fallbackName: string): StringFields {\n const match = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n/.exec(raw);\n if (match === null) {\n throw new ConfigurationError(`Skill ${fallbackName} is missing frontmatter`, {\n code: \"missing_frontmatter\",\n });\n }\n const frontmatter = match[1] ?? \"\";\n // EC-5: guard against syntactically invalid frontmatter so the loader\n // surfaces schema_invalid rather than crashing.\n try {\n return toStringFields(parseSimpleYaml(frontmatter));\n } catch (cause) {\n const detail = cause instanceof Error ? cause.message : String(cause);\n throw new ConfigurationError(\n `Skill ${fallbackName} has malformed YAML frontmatter: ${detail}`,\n { code: \"schema_invalid\", cause },\n );\n }\n}\n\nfunction resolveName(fields: StringFields, fallbackName: string): string {\n if (hasContent(fields.name)) return fields.name;\n if (hasContent(fallbackName)) return fallbackName;\n throw new ConfigurationError(\"Skill at unknown path is missing required field: name\", {\n code: \"schema_invalid\",\n });\n}\n\nfunction ensureRequiredFields(fields: StringFields, name: string): void {\n if (!hasContent(fields.description)) {\n throw new ConfigurationError(`Skill ${name} is missing required field: description`, {\n code: \"schema_invalid\",\n });\n }\n}\n\nfunction buildFrontmatter(fields: StringFields, name: string): SkillFrontmatter {\n const description = fields.description;\n if (description === undefined) {\n // ensureRequiredFields already threw; this is unreachable but satisfies TS\n throw new ConfigurationError(`Skill ${name} missing description`, { code: \"schema_invalid\" });\n }\n const result: SkillFrontmatter = { name, description };\n if (hasContent(fields.category)) result.category = fields.category;\n const deps = parseDependencies(fields.dependencies);\n if (deps !== undefined) result.dependencies = deps;\n return result;\n}\n\nfunction parseDependencies(raw: string | undefined): string[] | undefined {\n if (!hasContent(raw)) return undefined;\n const deps = (raw as string)\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n return deps.length > 0 ? deps : undefined;\n}\n\nfunction hasContent(value: string | undefined): value is string {\n return value !== undefined && value.trim().length > 0;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { ConfigurationError } from \"../../../errors.js\";\nimport { assertNoSymlinkEscape, safePathJoin } from \"../../security/path-guard.js\";\nimport { readWorkspaceDir } from \"../config/workspace-dir.js\";\nimport { parseSkillFrontmatter } from \"./skill-frontmatter.js\";\n\n/**\n * A discovered skill's metadata. The skill BODY is never included — only the\n * strict frontmatter fields plus the resolved `source` path.\n *\n * Public via `@theokit/sdk/skills`.\n *\n * @public\n */\nexport interface Skill {\n name: string;\n description: string;\n /** Absolute path to the discovered `SKILL.md`. */\n source: string;\n category?: string;\n dependencies?: string[];\n}\n\n/**\n * Information passed to `onInvalidSkill` when a `SKILL.md` is present but its\n * frontmatter is malformed (missing required field or invalid YAML).\n *\n * @public\n */\nexport interface InvalidSkillInfo {\n /** The skill directory name (used as the fallback skill name). */\n name: string;\n /** Absolute path to the offending `SKILL.md`. */\n source: string;\n /** Typed reason: `missing_frontmatter` or `schema_invalid`. */\n code: string;\n message: string;\n}\n\n/**\n * Options for {@link discoverSkills}.\n *\n * @public\n */\nexport interface DiscoverSkillsOptions {\n /**\n * Called once per directory that contains a `SKILL.md` with malformed\n * frontmatter. The skill is excluded from the result; discovery continues\n * (strict-frontmatter ADR / EC-5). A directory WITHOUT a `SKILL.md` is NOT a\n * malformed skill and does not trigger this callback.\n *\n * Default: no-op (a library primitive must not write to the consumer's\n * stderr by default).\n */\n onInvalidSkill?: (info: InvalidSkillInfo) => void;\n}\n\n/**\n * Discover `SKILL.md` skills under an arbitrary directory.\n *\n * For each immediate subdirectory `<dir>/<name>/` containing a `SKILL.md`, the\n * file's strict YAML frontmatter is parsed (`name`/`description` required;\n * `category`/`dependencies` optional). Malformed skills are skipped (optionally\n * reported via {@link DiscoverSkillsOptions.onInvalidSkill}); a subdirectory\n * whose realpath escapes `dir` (via symlink) is skipped (symlink-escape guard,\n * reusing `@theokit/sdk/path-safety`).\n *\n * NEVER throws: a missing, unreadable, or non-directory `dir` yields `[]`.\n *\n * Discovery order follows the filesystem `readdir` order (OS-dependent). Sort\n * the result before {@link buildSkillsBlock} if a stable block order matters.\n *\n * Public via `@theokit/sdk/skills`.\n *\n * @public\n */\nexport async function discoverSkills(\n dir: string,\n options?: DiscoverSkillsOptions,\n): Promise<Skill[]> {\n let entries: Awaited<ReturnType<typeof readWorkspaceDir>>;\n try {\n entries = await readWorkspaceDir(dir, \"skills_read_error\", \"skills directory\");\n } catch {\n // never-throw contract: unreadable / not-a-directory → no skills (EC-1)\n return [];\n }\n\n const skills: Skill[] = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n let skillDir: string;\n try {\n skillDir = safePathJoin(dir, entry.name);\n assertNoSymlinkEscape(skillDir, dir);\n } catch {\n continue;\n }\n const skillPath = join(skillDir, \"SKILL.md\");\n let raw: string;\n try {\n raw = await readFile(skillPath, \"utf8\");\n } catch {\n // no SKILL.md in this subdir → not a skill, not an error (EC-2)\n continue;\n }\n const skill = tryParseSkill(raw, entry.name, skillPath, options);\n if (skill !== undefined) skills.push(skill);\n }\n return skills;\n}\n\nfunction tryParseSkill(\n raw: string,\n fallbackName: string,\n source: string,\n options: DiscoverSkillsOptions | undefined,\n): Skill | undefined {\n try {\n const frontmatter = parseSkillFrontmatter(raw, fallbackName);\n const skill: Skill = {\n name: frontmatter.name,\n description: frontmatter.description,\n source,\n };\n if (frontmatter.category !== undefined) skill.category = frontmatter.category;\n if (frontmatter.dependencies !== undefined) skill.dependencies = frontmatter.dependencies;\n return skill;\n } catch (cause) {\n if (cause instanceof ConfigurationError) {\n options?.onInvalidSkill?.({\n name: fallbackName,\n source,\n code: cause.code ?? \"unknown\",\n message: cause.message,\n });\n return undefined;\n }\n throw cause;\n }\n}\n","/**\n * Block-body XML escape (ADR D9 — prompt-injection defence).\n *\n * Order matters: `&` MUST be escaped first so subsequent `<`/`>` replacements\n * do not double-encode the `&` characters they introduce.\n *\n * @internal\n */\nexport const escapeBlockBody = (s: string): string =>\n s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n","import { escapeBlockBody } from \"../system-prompt/escape.js\";\n\n/**\n * Render the `<skills>` system-prompt block from a skill list.\n *\n * Input is the structural subset `{ name, description }` — the skill BODY is\n * NOT in the type, so it cannot leak into the prompt. Both fields are passed\n * through `escapeBlockBody` to neutralise prompt-injection vectors hidden in\n * user-controlled SKILL.md frontmatter (injection-escape ADR).\n *\n * Returns `undefined` for an empty list so the caller can omit the block.\n *\n * Public via `@theokit/sdk/skills`.\n *\n * @public\n */\nexport function buildSkillsBlock(\n skills: ReadonlyArray<{ name: string; description: string }>,\n): string | undefined {\n if (skills.length === 0) return undefined;\n const lines = skills.map(\n (skill) => ` - ${escapeBlockBody(skill.name)}: ${escapeBlockBody(skill.description)}`,\n );\n return `<skills>\\n${lines.join(\"\\n\")}\\n</skills>`;\n}\n"]}
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkVKJ7V7EB_cjs = require('./chunk-VKJ7V7EB.cjs');
4
- var chunk2YGIBOUH_cjs = require('./chunk-2YGIBOUH.cjs');
4
+ var chunkLPVIRJVF_cjs = require('./chunk-LPVIRJVF.cjs');
5
5
  var crypto = require('crypto');
6
6
  var fs = require('fs');
7
7
  var path = require('path');
8
8
 
9
- var PathTraversalError = class extends chunk2YGIBOUH_cjs.ConfigurationError {
9
+ var PathTraversalError = class extends chunkLPVIRJVF_cjs.ConfigurationError {
10
10
  name = "PathTraversalError";
11
11
  constructor(input, resolvedPath) {
12
12
  super(`Path traversal attempt: ${input} \u2192 ${resolvedPath}`, {
@@ -14,7 +14,7 @@ var PathTraversalError = class extends chunk2YGIBOUH_cjs.ConfigurationError {
14
14
  });
15
15
  }
16
16
  };
17
- var ForbiddenPathError = class extends chunk2YGIBOUH_cjs.ConfigurationError {
17
+ var ForbiddenPathError = class extends chunkLPVIRJVF_cjs.ConfigurationError {
18
18
  name = "ForbiddenPathError";
19
19
  constructor(path) {
20
20
  super(
@@ -184,13 +184,13 @@ function rejectParentTraversal(input, normalized) {
184
184
  function sanitizeIdentifier(input, options) {
185
185
  const maxLen = options?.maxLen ?? 64;
186
186
  if (input.length === 0 || input.length > maxLen) {
187
- throw new chunk2YGIBOUH_cjs.ConfigurationError(`Identifier length out of range (1-${maxLen}): "${input}"`, {
187
+ throw new chunkLPVIRJVF_cjs.ConfigurationError(`Identifier length out of range (1-${maxLen}): "${input}"`, {
188
188
  code: "invalid_identifier"
189
189
  });
190
190
  }
191
191
  rejectNulAndControlChars(input, "identifier");
192
192
  if (!IDENTIFIER_PATTERN.test(input)) {
193
- throw new chunk2YGIBOUH_cjs.ConfigurationError(`Identifier contains invalid characters: "${input}"`, {
193
+ throw new chunkLPVIRJVF_cjs.ConfigurationError(`Identifier contains invalid characters: "${input}"`, {
194
194
  code: "invalid_identifier"
195
195
  });
196
196
  }
@@ -198,7 +198,7 @@ function sanitizeIdentifier(input, options) {
198
198
  }
199
199
  function safeFilenameForId(id, options) {
200
200
  if (id.length === 0) {
201
- throw new chunk2YGIBOUH_cjs.ConfigurationError("Filename id must be a non-empty string", {
201
+ throw new chunkLPVIRJVF_cjs.ConfigurationError("Filename id must be a non-empty string", {
202
202
  code: "invalid_filename_id"
203
203
  });
204
204
  }
@@ -218,5 +218,5 @@ exports.safeFilenameForId = safeFilenameForId;
218
218
  exports.safePathJoin = safePathJoin;
219
219
  exports.sanitizeIdentifier = sanitizeIdentifier;
220
220
  exports.validateArtifactPath = validateArtifactPath;
221
- //# sourceMappingURL=chunk-YTO5BRBD.cjs.map
222
- //# sourceMappingURL=chunk-YTO5BRBD.cjs.map
221
+ //# sourceMappingURL=chunk-ZT57WTUJ.cjs.map
222
+ //# sourceMappingURL=chunk-ZT57WTUJ.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/internal/security/path-guard.ts"],"names":["ConfigurationError","atOrInsideRoot","resolve","path","realpathSync","lstatSync","readlinkSync","dirname","createHash"],"mappings":"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","file":"chunk-ZT57WTUJ.cjs","sourcesContent":["/**\n * Canonical path-guard module (ADRs D79-D81).\n *\n * Three primitives + one typed error:\n * - `safePathJoin(base, ...parts)` — resolve THEN prefix-check (ADR D80).\n * - `assertNoSymlinkEscape(path, base)` — `realpathSync` resolves entire\n * symlink chain (EC-1 fix; Hermes v0.2 #386, #61).\n * - `sanitizeIdentifier(input, { maxLen })` — strict grammar\n * `^[a-z0-9][a-z0-9-_]*$` (ADR D81; case-insensitive on input,\n * lowercase on output).\n * - `PathTraversalError` — extends ConfigurationError with code\n * `path_traversal` (ADR D65: no new hierarchy).\n *\n * Wire at all sites where user input becomes a path. CI lint gate\n * `tests/lint/no-unguarded-path-input.test.ts` prevents regression\n * (ADR D85).\n *\n * @internal\n */\n\nimport { createHash } from \"node:crypto\";\nimport { lstatSync, readlinkSync, realpathSync, type Stats } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\n\nimport { ConfigurationError } from \"../../errors.js\";\nimport { atOrInsideRoot } from \"../runtime/context/path-containment.js\";\n\n/**\n * Thrown when a path operation would escape its allowed base directory.\n * Extends `ConfigurationError` (no new error hierarchy per ADR D65).\n *\n */\nexport class PathTraversalError extends ConfigurationError {\n override readonly name: string = \"PathTraversalError\";\n\n constructor(input: string, resolvedPath: string) {\n super(`Path traversal attempt: ${input} → ${resolvedPath}`, {\n code: \"path_traversal\",\n });\n }\n}\n\n/**\n * Thrown when an agent tool is asked to read or write a sensitive path\n * that the blocklist forbids (`.env`, `.git/`, `node_modules/`, `.theo/`,\n * lock files). Distinct from `PathTraversalError` because the path is\n * lexically inside the project — it is just sensitive.\n *\n * Extends `ConfigurationError` (no new error hierarchy per ADR D65).\n *\n * @public\n */\nexport class ForbiddenPathError extends ConfigurationError {\n override readonly name: string = \"ForbiddenPathError\";\n\n constructor(path: string) {\n super(\n `Path '${path}' is in the sensitive-file blocklist (.env, .git/, node_modules/, .theo/, lock files)`,\n {\n code: \"forbidden_path\",\n },\n );\n }\n}\n\n/**\n * Is `target` the same as `base`, or strictly under it?\n *\n * The prefix must not double the separator. `resolve` strips a trailing `sep` from every base\n * EXCEPT the filesystem root, where `resolve(sep) === sep`; there `base + sep` would be `//`, which\n * no absolute path starts with, so a root base rejected EVERY path (#149). Only the root takes that\n * branch — for any other base the prefix is unchanged, so containment is not weakened.\n *\n * Both containment checks in this module go through here: they had the same defect and were fixed\n * one at a time, which is exactly how the two drifted apart in the first place.\n *\n * Both arguments MUST already be resolved absolute paths.\n */\nfunction isInside(target: string, base: string): boolean {\n // B-117 — compared after symlink resolution, via the shared rule. A prefix test judges a link by\n // its NAME: `<base>/link/x` where `link` points outside is lexically inside and physically not.\n // Measured reachable from the plugin manager and the MCP client before this was changed.\n //\n // The root itself stays allowed, which `insideRoot` alone does not answer: it returns false for\n // `target === base` (correct for its own caller, wrong here, where `safePathJoin(base)` with no\n // parts must return `base`). Kept as an explicit second clause rather than by weakening the\n // shared rule for everyone.\n return atOrInsideRoot(target, base);\n}\n\n/**\n * Join `base` with `...parts` and ensure the resolved absolute path stays\n * under `base`. Resolves FIRST, then prefix-checks (ADR D80) — prevents\n * normalized-escape bypasses like `subdir/.\\\\./bar`.\n *\n * Returns the safe absolute path. Throws `PathTraversalError` if escape.\n *\n */\nexport function safePathJoin(base: string, ...parts: string[]): string {\n if (base === \"\") {\n throw new Error(\"safePathJoin: base must be non-empty\");\n }\n // T5.5 — NUL byte + C0/DEL control char rejection at the boundary.\n // Apply before path resolution so a malicious input never reaches\n // `resolve` (which on some platforms behaved unexpectedly with NUL\n // and in N-API callers historically silently truncated).\n rejectNulAndControlChars(base, \"base\");\n for (const part of parts) {\n rejectNulAndControlChars(part, \"path segment\");\n }\n const baseResolved = resolve(base);\n const target = resolve(base, ...parts);\n if (!isInside(target, baseResolved)) {\n throw new PathTraversalError(parts.join(\"/\"), target);\n }\n return target;\n}\n\n/**\n * T5.5 — Reject NUL (`\\x00`) and C0/DEL control characters\n * (`\\x01-\\x1F`, `\\x7F`) in any path-shaped or identifier-shaped input.\n * Centralizes the check so every public path-guard / sanitize entrypoint\n * shares the same defense.\n *\n * Throws `PathTraversalError` (the same shape as other path-shape\n * rejections) so callers don't need to learn a new error class.\n *\n * @internal\n */\nfunction rejectNulAndControlChars(input: string, role: string): void {\n for (let i = 0; i < input.length; i++) {\n const code = input.charCodeAt(i);\n if (code === 0x00 || (code >= 0x01 && code <= 0x1f) || code === 0x7f) {\n const label = code === 0x00 ? \"<nul-byte>\" : `<control-char-0x${code.toString(16)}>`;\n throw new PathTraversalError(`${role}: ${input}`, label);\n }\n }\n}\n\n/**\n * Assert that `path` — including every directory component in the chain —\n * stays under `base` after symlink resolution. No-op when nothing on the\n * path exists yet.\n *\n * Two-bug history:\n * 1. **EC-1** (original fix, kept): a multi-level symlink chain A → B → C\n * must be resolved end-to-end. `realpathSync` does this in 1 syscall.\n * 2. **Defence-in-depth** (added v1.x): the previous implementation only\n * called `lstatSync(path)` on the terminal component. If an INTERMEDIATE\n * directory was a symlink (`base/inner-symlink → /outside`), `lstat` on\n * `base/inner-symlink/file.txt` followed the symlink and reported the\n * regular file — escape went undetected. Fix: walk up to the nearest\n * existing ancestor and `realpath` THAT, then re-attach the suffix and\n * check the result against the canonical base.\n *\n */\nexport function assertNoSymlinkEscape(path: string, base: string): void {\n // T5.5 — reject NUL / control chars before any FS call (a NUL byte\n // in the path used to silently truncate at the C boundary on legacy\n // libc — defense in depth even on modern Node).\n rejectNulAndControlChars(path, \"path\");\n rejectNulAndControlChars(base, \"base\");\n // Canonical base — symlinks in the base path itself are absorbed once here.\n let baseResolved: string;\n try {\n baseResolved = realpathSync(base);\n } catch {\n // base doesn't exist as a real directory yet — fall back to lexical resolve.\n baseResolved = resolve(base);\n }\n\n // Find the deepest ancestor of `path` that exists, then realpath it.\n // Anything from there onward is \"not yet on disk\" and contributes only\n // its lexical suffix. This covers three cases:\n // - path exists (regular file or symlink at any depth) → realpath the full path\n // - path doesn't exist but intermediate dir is a symlink → realpath the ancestor\n // - nothing on the path exists → no escape risk (return)\n const resolved = realpathOfDeepestExisting(path);\n if (resolved === undefined) return; // path has no existing prefix — nothing to attack\n\n if (!isInside(resolved, baseResolved)) {\n throw new PathTraversalError(`symlink ${path}`, resolved);\n }\n}\n\n/**\n * Find the deepest ancestor of `path` that exists on disk, resolve all\n * symlinks in that ancestor via `realpathSync`, and re-attach the\n * lexical suffix. Returns `undefined` when no ancestor exists.\n *\n * Handles dangling symlinks: if the terminal IS a symlink but its target\n * is missing, we still detect escape via `readlinkSync` + parent resolve.\n */\nfunction realpathOfDeepestExisting(path: string): string | undefined {\n // First try the full path — the common case.\n try {\n return realpathSync(path);\n } catch {\n // Not resolvable. Two sub-cases.\n }\n\n // Sub-case A: terminal is a dangling symlink.\n try {\n const stat: Stats = lstatSync(path);\n if (stat.isSymbolicLink()) {\n const target = readlinkSync(path);\n // Resolve target relative to the REAL parent dir, so intermediate\n // symlinks in the parent chain are absorbed.\n const parentReal = realpathOfDeepestExisting(dirname(path));\n const parentBase = parentReal ?? dirname(path);\n return resolve(parentBase, target);\n }\n } catch {\n // lstat failed too — terminal doesn't exist at all.\n }\n\n // Sub-case B: walk up to the nearest existing ancestor, then re-attach\n // the suffix lexically.\n let cursor = dirname(path);\n let suffix = path.slice(cursor.length);\n while (cursor !== dirname(cursor)) {\n try {\n const real = realpathSync(cursor);\n // Reconstruct: ancestor's realpath + remaining (still-lexical) suffix\n return resolve(real, `.${suffix}`);\n } catch {\n suffix = path.slice(dirname(cursor).length);\n cursor = dirname(cursor);\n }\n }\n // Reached filesystem root without finding any existing ancestor.\n return undefined;\n}\n\nconst LOCK_FILES = new Set([\"pnpm-lock.yaml\", \"package-lock.json\", \"yarn.lock\", \"bun.lockb\"]);\n\n// T5.6 — top-level credential dot-dirs / dot-files. Matching against\n// the FIRST path segment (lowercase). Adding any entry here costs a\n// CHANGELOG note + an explicit case-fold test (entries are lowercased\n// at module load).\nconst SENSITIVE_FIRST_SEGMENTS = new Set([\n \".ssh\",\n \".aws\",\n \".docker\",\n \".kube\",\n \".npmrc\",\n \".netrc\",\n \".pgpass\",\n]);\n\n// T5.6 — credential basenames blocked at ANY depth (lowercase). Catches\n// the developer-laptop case where an agent recurses into a subdir.\nconst SENSITIVE_BASENAMES = new Set([\n \"id_rsa\",\n \"id_ed25519\",\n \"id_ecdsa\",\n \"id_dsa\",\n \"authorized_keys\",\n \"known_hosts\",\n \".npmrc\",\n \".netrc\",\n \".pgpass\",\n]);\n\n// T5.6 — extension suffixes blocked at ANY depth (lowercase). Covers\n// the entire `*.pem` / `*.key` private-material family.\nconst SENSITIVE_SUFFIXES = [\".pem\", \".key\", \".p12\", \".pfx\"];\n\n/**\n * Decide whether a project-relative path points to a known-sensitive file\n * that a coding agent must not read or write.\n *\n * Universal blocklist (works for any agent operating on a project tree):\n *\n * - `.env`, `.env.<anything>` — except `.env.example` (template safe to read)\n * - `.git/` — version control internals\n * - `node_modules/` — dependency cache (changes don't belong to the user)\n * - `.theo/` — TheoKit build artefacts / state\n * - Lock files at any depth: `pnpm-lock.yaml`, `package-lock.json`,\n * `yarn.lock`, `bun.lockb`\n *\n * Operates on path segments (forward-slash normalized). Cross-platform safe.\n *\n * Use together with `safePathJoin` + `assertNoSymlinkEscape`: the former two\n * defeat traversal, this one defeats reading a file that is lexically inside\n * the project but should not be agent-visible.\n *\n * @public\n */\nexport function isForbiddenPath(input: string): boolean {\n // T5.6 — lowercase normalization defeats case-only bypass on\n // case-insensitive filesystems (Windows/macOS-default) where `.ENV`\n // and `.env` map to the same inode but a case-sensitive string\n // check passes the former.\n const normalized = input.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\").toLowerCase();\n if (normalized.length === 0) return false;\n\n const segments = normalized.split(\"/\").filter((s) => s.length > 0);\n if (segments.length === 0) return false;\n\n if (isForbiddenFirstSegment(segments[0]!)) return true;\n if (isForbiddenBasename(segments[segments.length - 1]!)) return true;\n return false;\n}\n\nfunction isForbiddenFirstSegment(first: string): boolean {\n // .env.example is explicitly allowlisted (template safe to read)\n if (first === \".env.example\") return false;\n if (first === \".env\") return true;\n if (/^\\.env\\./.test(first)) return true;\n if (first === \".git\" || first === \"node_modules\" || first === \".theo\") return true;\n return SENSITIVE_FIRST_SEGMENTS.has(first);\n}\n\nfunction isForbiddenBasename(basename: string): boolean {\n if (LOCK_FILES.has(basename)) return true;\n if (SENSITIVE_BASENAMES.has(basename)) return true;\n for (const suffix of SENSITIVE_SUFFIXES) {\n if (basename.endsWith(suffix)) return true;\n }\n return false;\n}\n\nconst IDENTIFIER_PATTERN = /^[a-z0-9][a-z0-9\\-_]*$/i;\n\n/**\n * Validate that `input` is a safe path component (skill name, agent ID,\n * namespace, etc.) and return its lowercase form. Strict grammar\n * `^[a-z0-9][a-z0-9-_]*$` rejects path separators, dots, null bytes,\n * whitespace, unicode invisible chars, and any leading `-`/`_`.\n *\n * @param input - User-supplied identifier candidate.\n * @param options.maxLen - Maximum allowed length (default 64).\n * @returns Lowercase form of `input`.\n * @throws `ConfigurationError` with code `invalid_identifier` on rejection.\n *\n * @internal\n */\n/**\n * T1.4 — validate a relative artifact path string BEFORE it is used to look\n * up a fixture or to fetch from PaaS. Rejects every well-known traversal\n * vector at the boundary, throwing `PathTraversalError`.\n *\n * Vectors rejected:\n * - classic `..` parent-directory traversal (any segment).\n * - backslash separators (Windows-style `..\\\\windows`).\n * - URL-encoded `%2e%2e` / `%2E%2E` (double-decoded traversal).\n * - NUL byte injection (`\\x00`).\n * - Windows drive letter prefix (`C:`, `D:\\\\...`).\n * - Home-tilde expansion (`~/`, `~root/...`).\n * - Absolute paths starting with `/`.\n *\n * Does NOT touch the filesystem — the call is shape-only. Live symlink\n * traversal protection happens via `assertNoSymlinkEscape` at the FS-resolve\n * boundary.\n *\n * @param input - Caller-supplied artifact path.\n * @throws `PathTraversalError` on any rejection.\n *\n * @internal\n */\nexport function validateArtifactPath(input: string): void {\n rejectKnownPrefixVectors(input);\n const normalized = decodeAndNormalize(input);\n rejectParentTraversal(input, normalized);\n}\n\nfunction rejectKnownPrefixVectors(input: string): void {\n if (input.includes(\"\\x00\")) {\n throw new PathTraversalError(input, \"<nul-byte>\");\n }\n if (input.startsWith(\"/\") || input.startsWith(\"~\")) {\n throw new PathTraversalError(input, input);\n }\n if (/^[A-Za-z]:[\\\\/]?/.test(input)) {\n throw new PathTraversalError(input, input);\n }\n}\n\nfunction decodeAndNormalize(input: string): string {\n // URL-encoded traversal — 2 passes catches `%252e%252e`.\n // Malformed sequences (decodeURIComponent throws) are themselves a rejection.\n let decoded = input;\n for (let i = 0; i < 2; i += 1) {\n try {\n const next = decodeURIComponent(decoded);\n if (next === decoded) break;\n decoded = next;\n } catch {\n throw new PathTraversalError(input, \"<malformed-url-encoding>\");\n }\n }\n // Normalize backslash to forward slash before segment-walking.\n return decoded.replace(/\\\\/g, \"/\");\n}\n\nfunction rejectParentTraversal(input: string, normalized: string): void {\n for (const segment of normalized.split(\"/\")) {\n if (segment === \"..\" || segment === \"..%00\") {\n throw new PathTraversalError(input, normalized);\n }\n }\n // Defense in depth: literal `..` anywhere in the normalized string.\n if (normalized.includes(\"..\")) {\n throw new PathTraversalError(input, normalized);\n }\n}\n\nexport function sanitizeIdentifier(input: string, options?: { maxLen?: number }): string {\n const maxLen = options?.maxLen ?? 64;\n if (input.length === 0 || input.length > maxLen) {\n throw new ConfigurationError(`Identifier length out of range (1-${maxLen}): \"${input}\"`, {\n code: \"invalid_identifier\",\n });\n }\n // T5.5 — explicit NUL / control char rejection ahead of the generic\n // pattern check. The IDENTIFIER_PATTERN regex already excludes these\n // (they are not in `[a-z0-9\\-_]`), but routing them through the same\n // helper used by safePathJoin gives operators a precise diagnostic\n // (\"nul-byte\" / \"control-char-0x..\") instead of the generic\n // \"invalid characters\" message — making prompt-injection traces\n // legible per Unbreakable Rule 3.\n rejectNulAndControlChars(input, \"identifier\");\n if (!IDENTIFIER_PATTERN.test(input)) {\n throw new ConfigurationError(`Identifier contains invalid characters: \"${input}\"`, {\n code: \"invalid_identifier\",\n });\n }\n return input.toLowerCase();\n}\n\n/**\n * Convert ANY opaque id (agent id, run id, conversation id, namespace, email,\n * arbitrary string) into a deterministic, filesystem-safe filename component.\n *\n * Unlike {@link sanitizeIdentifier} (which THROWS on non-conforming input),\n * this is a total function: it NEVER throws on a non-empty string. It returns\n * the lowercased id verbatim when it already matches the safe grammar\n * `^[a-z0-9][a-z0-9-_]*$` and fits `maxLen` (so UUIDs, hashes, and slugs stay\n * human-readable), otherwise a deterministic `h-<16 hex>` sha256 token\n * (collision-resistant and always a valid filename). The output charset is\n * always `[a-z0-9_-]`, safe as a literal path segment on every filesystem.\n *\n * @param id - any opaque identifier (must be a non-empty string)\n * @param options.maxLen - max length for the passthrough branch (default 128).\n * Ids longer than this are hashed; the hash token itself is always short.\n * @throws ConfigurationError (code `invalid_filename_id`) only on empty input.\n *\n * @example\n * safeFilenameForId(\"550e8400-e29b-41d4-a716-446655440000\") // passthrough\n * safeFilenameForId(\"user@example.com\") // \"h-<16hex>\"\n *\n */\nexport function safeFilenameForId(id: string, options?: { maxLen?: number }): string {\n if (id.length === 0) {\n throw new ConfigurationError(\"Filename id must be a non-empty string\", {\n code: \"invalid_filename_id\",\n });\n }\n const maxLen = options?.maxLen ?? 128;\n const lower = id.toLowerCase();\n if (lower.length <= maxLen && IDENTIFIER_PATTERN.test(lower)) {\n return lower;\n }\n return `h-${createHash(\"sha256\").update(id).digest(\"hex\").slice(0, 16)}`;\n}\n"]}
@@ -0,0 +1,21 @@
1
+ export { COMPACT_SUMMARY_MARKER, COMPACT_USER_MESSAGE_MAX_TOKENS, autoCompactIfNeeded, buildDefaultSummarizer, compactSessionTranscript, isCompactSummary, resolveSummarizerRoute, shouldAutoCompact } from './chunk-LS3LMQ23.js';
2
+ import './chunk-GBBDINFK.js';
3
+ import './chunk-4QEC4CCS.js';
4
+ import './chunk-FFM3SJTQ.js';
5
+ import './chunk-FD2UT76F.js';
6
+ import './chunk-U54XCYG3.js';
7
+ import './chunk-NAF4L3T6.js';
8
+ import './chunk-N5CR3TJZ.js';
9
+ import './chunk-2XLKLVVR.js';
10
+ import './chunk-6AZDM6LK.js';
11
+ import './chunk-HE4BIAOS.js';
12
+ import './chunk-HSQ5Q3I5.js';
13
+ import './chunk-SSDD676S.js';
14
+ import './chunk-3V7UJLQT.js';
15
+ import './chunk-5NBUH3NO.js';
16
+ import './chunk-SK4QLUBK.js';
17
+ import './chunk-RIAM53CP.js';
18
+ import './chunk-U4UJHOSH.js';
19
+ import './chunk-5F5NWKPN.js';
20
+ //# sourceMappingURL=compact-session-4MNKNMO2.js.map
21
+ //# sourceMappingURL=compact-session-4MNKNMO2.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"compact-session-XLXC2CZN.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"compact-session-4MNKNMO2.js"}