@theokit/sdk 4.38.0 → 4.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/CHANGELOG.md +237 -0
  2. package/dist/a2a/index.cjs +3 -3
  3. package/dist/a2a/index.js +1 -1
  4. package/dist/a2a/subagent.d.cts +1 -0
  5. package/dist/a2a/subagent.d.ts +1 -0
  6. package/dist/{agent-U3lBX-5t.d.cts → agent-D7bRK9Kg.d.cts} +70 -5
  7. package/dist/agent-I3EZZR6S.cjs +55 -0
  8. package/dist/{agent-2GZC4W2A.cjs.map → agent-I3EZZR6S.cjs.map} +1 -1
  9. package/dist/agent-KKZYLY5D.js +46 -0
  10. package/dist/{agent-3H3UKD6U.js.map → agent-KKZYLY5D.js.map} +1 -1
  11. package/dist/{agent-C3AEtM-W.d.ts → agent-ZCZa7YQv.d.ts} +70 -5
  12. package/dist/agent-session-store-N4TVKHBU.cjs +23 -0
  13. package/dist/agent-session-store-N4TVKHBU.cjs.map +1 -0
  14. package/dist/agent-session-store-RHMHP5DG.js +6 -0
  15. package/dist/agent-session-store-RHMHP5DG.js.map +1 -0
  16. package/dist/agent.d.ts +37 -1
  17. package/dist/auth/index.cjs +15 -15
  18. package/dist/auth/index.js +4 -4
  19. package/dist/{batch-LXSALQC3.js → batch-6KQM3EBA.js} +12 -12
  20. package/dist/batch-6KQM3EBA.js.map +1 -0
  21. package/dist/{batch-NZGN6SFV.cjs → batch-X6JKGDPK.cjs} +26 -26
  22. package/dist/batch-X6JKGDPK.cjs.map +1 -0
  23. package/dist/chunk-2RW7K6FN.cjs +34 -0
  24. package/dist/chunk-2RW7K6FN.cjs.map +1 -0
  25. package/dist/chunk-3I4B3OIX.js +105 -0
  26. package/dist/chunk-3I4B3OIX.js.map +1 -0
  27. package/dist/{chunk-KWXC6ERT.js → chunk-42IFCKQZ.js} +5 -5
  28. package/dist/{chunk-KWXC6ERT.js.map → chunk-42IFCKQZ.js.map} +1 -1
  29. package/dist/{chunk-4APWS2YF.js → chunk-4F7JQZOX.js} +9 -36
  30. package/dist/chunk-4F7JQZOX.js.map +1 -0
  31. package/dist/{chunk-VYD6BGKK.js → chunk-4JSZYSGW.js} +3 -3
  32. package/dist/{chunk-VYD6BGKK.js.map → chunk-4JSZYSGW.js.map} +1 -1
  33. package/dist/{chunk-A6GXYF2Q.js → chunk-65ONFZWM.js} +7 -6
  34. package/dist/chunk-65ONFZWM.js.map +1 -0
  35. package/dist/{chunk-SGTMDQ4O.js → chunk-6EEYRFJC.js} +5 -5
  36. package/dist/{chunk-SGTMDQ4O.js.map → chunk-6EEYRFJC.js.map} +1 -1
  37. package/dist/{chunk-M4OGSS66.cjs → chunk-6LGQECT7.cjs} +11 -11
  38. package/dist/{chunk-M4OGSS66.cjs.map → chunk-6LGQECT7.cjs.map} +1 -1
  39. package/dist/{chunk-KTXOHCAE.cjs → chunk-6NEHIHFU.cjs} +4 -4
  40. package/dist/{chunk-KTXOHCAE.cjs.map → chunk-6NEHIHFU.cjs.map} +1 -1
  41. package/dist/chunk-6YNYA7GD.cjs +103 -0
  42. package/dist/chunk-6YNYA7GD.cjs.map +1 -0
  43. package/dist/{chunk-2R6NBT5F.cjs → chunk-74D7KSBP.cjs} +11 -11
  44. package/dist/{chunk-2R6NBT5F.cjs.map → chunk-74D7KSBP.cjs.map} +1 -1
  45. package/dist/{chunk-6OIO4FYX.cjs → chunk-75DSEWTJ.cjs} +7 -7
  46. package/dist/{chunk-6OIO4FYX.cjs.map → chunk-75DSEWTJ.cjs.map} +1 -1
  47. package/dist/{chunk-3XRXORBS.cjs → chunk-7OLG7VI4.cjs} +4 -4
  48. package/dist/{chunk-3XRXORBS.cjs.map → chunk-7OLG7VI4.cjs.map} +1 -1
  49. package/dist/chunk-7U2HAAWB.cjs +199 -0
  50. package/dist/chunk-7U2HAAWB.cjs.map +1 -0
  51. package/dist/{chunk-QJQ2MAZF.cjs → chunk-7YBJZS5P.cjs} +8 -8
  52. package/dist/{chunk-QJQ2MAZF.cjs.map → chunk-7YBJZS5P.cjs.map} +1 -1
  53. package/dist/{chunk-ZFZYPLQI.js → chunk-AECV3G5Z.js} +4 -4
  54. package/dist/{chunk-ZFZYPLQI.js.map → chunk-AECV3G5Z.js.map} +1 -1
  55. package/dist/{chunk-QFWQLXCL.js → chunk-AR5MQZ3J.js} +3 -3
  56. package/dist/{chunk-QFWQLXCL.js.map → chunk-AR5MQZ3J.js.map} +1 -1
  57. package/dist/{chunk-G2F67XUR.cjs → chunk-B4YA6BRS.cjs} +13 -14
  58. package/dist/chunk-B4YA6BRS.cjs.map +1 -0
  59. package/dist/{chunk-BE3W4HYV.cjs → chunk-BCQ3E2ZG.cjs} +12 -3
  60. package/dist/chunk-BCQ3E2ZG.cjs.map +1 -0
  61. package/dist/{chunk-G7X2Y7Y2.cjs → chunk-BPN5ONSW.cjs} +182 -236
  62. package/dist/chunk-BPN5ONSW.cjs.map +1 -0
  63. package/dist/{chunk-XJ5TMOGA.js → chunk-BQDUEG4C.js} +3 -3
  64. package/dist/{chunk-XJ5TMOGA.js.map → chunk-BQDUEG4C.js.map} +1 -1
  65. package/dist/{chunk-OFWU6UKF.cjs → chunk-C7OP3FAK.cjs} +47 -11
  66. package/dist/chunk-C7OP3FAK.cjs.map +1 -0
  67. package/dist/{chunk-BUGVDCI5.cjs → chunk-CEIHCKTO.cjs} +4 -4
  68. package/dist/chunk-CEIHCKTO.cjs.map +1 -0
  69. package/dist/{chunk-3BSP7LSG.cjs → chunk-CN6UX5EV.cjs} +28 -56
  70. package/dist/chunk-CN6UX5EV.cjs.map +1 -0
  71. package/dist/{chunk-5BVBNE2F.js → chunk-D7IULBF2.js} +3 -3
  72. package/dist/{chunk-5BVBNE2F.js.map → chunk-D7IULBF2.js.map} +1 -1
  73. package/dist/{chunk-6ZGD7R27.cjs → chunk-DCXRHCZJ.cjs} +8 -75
  74. package/dist/chunk-DCXRHCZJ.cjs.map +1 -0
  75. package/dist/{chunk-YVI4YPUP.cjs → chunk-DGLLVCNB.cjs} +4 -4
  76. package/dist/{chunk-YVI4YPUP.cjs.map → chunk-DGLLVCNB.cjs.map} +1 -1
  77. package/dist/{chunk-JI34KBNC.js → chunk-DKFGUOWL.js} +3 -3
  78. package/dist/{chunk-JI34KBNC.js.map → chunk-DKFGUOWL.js.map} +1 -1
  79. package/dist/{chunk-ZET34IZE.cjs → chunk-DMTZ3FII.cjs} +5 -5
  80. package/dist/{chunk-ZET34IZE.cjs.map → chunk-DMTZ3FII.cjs.map} +1 -1
  81. package/dist/{chunk-6XZBKFQ7.js → chunk-DU7DE543.js} +3 -3
  82. package/dist/{chunk-6XZBKFQ7.js.map → chunk-DU7DE543.js.map} +1 -1
  83. package/dist/{chunk-VVMLMKYZ.cjs → chunk-DWY25VLP.cjs} +9 -9
  84. package/dist/{chunk-VVMLMKYZ.cjs.map → chunk-DWY25VLP.cjs.map} +1 -1
  85. package/dist/{chunk-A4XXV2C6.js → chunk-E2FFG33C.js} +5 -72
  86. package/dist/chunk-E2FFG33C.js.map +1 -0
  87. package/dist/{chunk-R4AMI7KD.cjs → chunk-E4IUN3JB.cjs} +15 -15
  88. package/dist/{chunk-R4AMI7KD.cjs.map → chunk-E4IUN3JB.cjs.map} +1 -1
  89. package/dist/{chunk-TKDWD3MU.cjs → chunk-ECHGWE47.cjs} +4 -4
  90. package/dist/{chunk-TKDWD3MU.cjs.map → chunk-ECHGWE47.cjs.map} +1 -1
  91. package/dist/{chunk-KL7E244K.cjs → chunk-ECW2MLEW.cjs} +4 -4
  92. package/dist/{chunk-KL7E244K.cjs.map → chunk-ECW2MLEW.cjs.map} +1 -1
  93. package/dist/{chunk-EDI7DBWO.js → chunk-ET6PHZRX.js} +3 -3
  94. package/dist/{chunk-EDI7DBWO.js.map → chunk-ET6PHZRX.js.map} +1 -1
  95. package/dist/{chunk-HLK35TD7.cjs → chunk-FRUBE44B.cjs} +24 -24
  96. package/dist/{chunk-HLK35TD7.cjs.map → chunk-FRUBE44B.cjs.map} +1 -1
  97. package/dist/{chunk-SRIF7HMN.cjs → chunk-FWBSDQZ7.cjs} +5 -5
  98. package/dist/{chunk-SRIF7HMN.cjs.map → chunk-FWBSDQZ7.cjs.map} +1 -1
  99. package/dist/{chunk-XKBJT7WI.cjs → chunk-G2Q3ZC6C.cjs} +4 -4
  100. package/dist/{chunk-XKBJT7WI.cjs.map → chunk-G2Q3ZC6C.cjs.map} +1 -1
  101. package/dist/{chunk-4MWBKBS4.cjs → chunk-G4XUXSRN.cjs} +12 -12
  102. package/dist/{chunk-4MWBKBS4.cjs.map → chunk-G4XUXSRN.cjs.map} +1 -1
  103. package/dist/{chunk-VUDH4D2M.js → chunk-GIRD3RWH.js} +282 -276
  104. package/dist/chunk-GIRD3RWH.js.map +1 -0
  105. package/dist/{chunk-BT6DFWZB.cjs → chunk-HIQFVHC6.cjs} +9 -9
  106. package/dist/{chunk-BT6DFWZB.cjs.map → chunk-HIQFVHC6.cjs.map} +1 -1
  107. package/dist/{chunk-UWEALKAN.js → chunk-HWNVAUK4.js} +3 -3
  108. package/dist/{chunk-UWEALKAN.js.map → chunk-HWNVAUK4.js.map} +1 -1
  109. package/dist/{chunk-3VKTDQMX.cjs → chunk-I53ZQHU6.cjs} +4 -4
  110. package/dist/{chunk-3VKTDQMX.cjs.map → chunk-I53ZQHU6.cjs.map} +1 -1
  111. package/dist/{chunk-A3MHE2MQ.cjs → chunk-IHFNRNTJ.cjs} +8 -8
  112. package/dist/{chunk-A3MHE2MQ.cjs.map → chunk-IHFNRNTJ.cjs.map} +1 -1
  113. package/dist/{chunk-UZBA6YYP.cjs → chunk-INSFS5GT.cjs} +540 -534
  114. package/dist/chunk-INSFS5GT.cjs.map +1 -0
  115. package/dist/{chunk-KCZW75PI.js → chunk-IVSD7L22.js} +12 -4
  116. package/dist/chunk-IVSD7L22.js.map +1 -0
  117. package/dist/{chunk-JCXIDFRI.js → chunk-J3UK2GMN.js} +3 -3
  118. package/dist/{chunk-JCXIDFRI.js.map → chunk-J3UK2GMN.js.map} +1 -1
  119. package/dist/{chunk-IBDE4R5L.cjs → chunk-J6T5LWJ4.cjs} +10 -9
  120. package/dist/chunk-J6T5LWJ4.cjs.map +1 -0
  121. package/dist/{chunk-AOZYORH7.js → chunk-JRLXEYR4.js} +21 -5
  122. package/dist/chunk-JRLXEYR4.js.map +1 -0
  123. package/dist/{chunk-EUB7YLU2.js → chunk-JZUPMTJY.js} +3 -3
  124. package/dist/{chunk-EUB7YLU2.js.map → chunk-JZUPMTJY.js.map} +1 -1
  125. package/dist/{chunk-ZK3BJ4XQ.js → chunk-KE6XKRLQ.js} +3 -3
  126. package/dist/{chunk-ZK3BJ4XQ.js.map → chunk-KE6XKRLQ.js.map} +1 -1
  127. package/dist/{chunk-4NVV3GRU.js → chunk-KGRIHEDT.js} +5 -5
  128. package/dist/{chunk-4NVV3GRU.js.map → chunk-KGRIHEDT.js.map} +1 -1
  129. package/dist/{chunk-EE24WJJR.js → chunk-KWUNN5J2.js} +5 -5
  130. package/dist/{chunk-EE24WJJR.js.map → chunk-KWUNN5J2.js.map} +1 -1
  131. package/dist/{chunk-LGCEYEU2.js → chunk-KX7JV5KM.js} +3 -3
  132. package/dist/{chunk-LGCEYEU2.js.map → chunk-KX7JV5KM.js.map} +1 -1
  133. package/dist/{chunk-2K7PRHDB.cjs → chunk-LALG2K33.cjs} +8 -8
  134. package/dist/{chunk-2K7PRHDB.cjs.map → chunk-LALG2K33.cjs.map} +1 -1
  135. package/dist/{chunk-4WIJSKFA.js → chunk-LGILIGV3.js} +3 -3
  136. package/dist/{chunk-4WIJSKFA.js.map → chunk-LGILIGV3.js.map} +1 -1
  137. package/dist/{chunk-7QDTZJRV.js → chunk-LJX2SQV2.js} +6 -6
  138. package/dist/{chunk-7QDTZJRV.js.map → chunk-LJX2SQV2.js.map} +1 -1
  139. package/dist/{chunk-ACHGT3D2.js → chunk-MC5EINBV.js} +44 -8
  140. package/dist/chunk-MC5EINBV.js.map +1 -0
  141. package/dist/{chunk-M6UUTNDT.js → chunk-ML5A5DOJ.js} +4 -4
  142. package/dist/{chunk-M6UUTNDT.js.map → chunk-ML5A5DOJ.js.map} +1 -1
  143. package/dist/{chunk-3MUIYMUG.cjs → chunk-N475ETD6.cjs} +17 -17
  144. package/dist/{chunk-3MUIYMUG.cjs.map → chunk-N475ETD6.cjs.map} +1 -1
  145. package/dist/chunk-OXNYIMZZ.js +31 -0
  146. package/dist/chunk-OXNYIMZZ.js.map +1 -0
  147. package/dist/{chunk-YCHC45BY.js → chunk-PI4RO4GR.js} +3 -3
  148. package/dist/{chunk-YCHC45BY.js.map → chunk-PI4RO4GR.js.map} +1 -1
  149. package/dist/chunk-QKE556YD.js +197 -0
  150. package/dist/chunk-QKE556YD.js.map +1 -0
  151. package/dist/{chunk-FV3YEMQ7.js → chunk-RP5HQVLD.js} +13 -14
  152. package/dist/chunk-RP5HQVLD.js.map +1 -0
  153. package/dist/chunk-SCFW5MJZ.js +100 -0
  154. package/dist/chunk-SCFW5MJZ.js.map +1 -0
  155. package/dist/{chunk-ZYOHF37V.js → chunk-SG5ZWT6C.js} +3 -3
  156. package/dist/{chunk-ZYOHF37V.js.map → chunk-SG5ZWT6C.js.map} +1 -1
  157. package/dist/{chunk-ED7ANP6W.cjs → chunk-TIMPJL5V.cjs} +4 -4
  158. package/dist/{chunk-ED7ANP6W.cjs.map → chunk-TIMPJL5V.cjs.map} +1 -1
  159. package/dist/{chunk-3XKVRLR2.js → chunk-TOTP24P6.js} +4 -4
  160. package/dist/{chunk-3XKVRLR2.js.map → chunk-TOTP24P6.js.map} +1 -1
  161. package/dist/{chunk-PG3QQLWS.cjs → chunk-USZTVNUQ.cjs} +5 -5
  162. package/dist/{chunk-PG3QQLWS.cjs.map → chunk-USZTVNUQ.cjs.map} +1 -1
  163. package/dist/{chunk-XS7SKY2F.js → chunk-V2RBCCN5.js} +3 -3
  164. package/dist/chunk-V2RBCCN5.js.map +1 -0
  165. package/dist/{chunk-D3SJLXYZ.cjs → chunk-VJYSQXN6.cjs} +10 -10
  166. package/dist/{chunk-D3SJLXYZ.cjs.map → chunk-VJYSQXN6.cjs.map} +1 -1
  167. package/dist/{chunk-MXRBNJ6D.cjs → chunk-W4WKVOOQ.cjs} +11 -11
  168. package/dist/{chunk-MXRBNJ6D.cjs.map → chunk-W4WKVOOQ.cjs.map} +1 -1
  169. package/dist/chunk-XYOHKCYG.cjs +109 -0
  170. package/dist/chunk-XYOHKCYG.cjs.map +1 -0
  171. package/dist/{chunk-UD2T7ISG.js → chunk-YP67XZES.js} +4 -4
  172. package/dist/{chunk-UD2T7ISG.js.map → chunk-YP67XZES.js.map} +1 -1
  173. package/dist/{chunk-HHUDNTZC.js → chunk-YRXY2A5L.js} +4 -4
  174. package/dist/{chunk-HHUDNTZC.js.map → chunk-YRXY2A5L.js.map} +1 -1
  175. package/dist/{chunk-6OKPJZMX.cjs → chunk-Z2CUEBXV.cjs} +25 -9
  176. package/dist/chunk-Z2CUEBXV.cjs.map +1 -0
  177. package/dist/{chunk-HI6G3SNY.js → chunk-ZYB6B7QJ.js} +72 -125
  178. package/dist/chunk-ZYB6B7QJ.js.map +1 -0
  179. package/dist/compact-session-PYEC3NZV.js +18 -0
  180. package/dist/{compact-session-RR3ILTES.js.map → compact-session-PYEC3NZV.js.map} +1 -1
  181. package/dist/compact-session-VVT6IBJG.cjs +55 -0
  182. package/dist/{compact-session-YOWJJPPB.cjs.map → compact-session-VVT6IBJG.cjs.map} +1 -1
  183. package/dist/compaction.cjs +16 -16
  184. package/dist/compaction.js +3 -3
  185. package/dist/concurrency.cjs +6 -6
  186. package/dist/concurrency.js +4 -4
  187. package/dist/context-2FZSC6VQ.cjs +22 -0
  188. package/dist/{context-Q6ISOCN2.cjs.map → context-2FZSC6VQ.cjs.map} +1 -1
  189. package/dist/context-ATJJAFOS.js +5 -0
  190. package/dist/{context-ZDBBPIHY.js.map → context-ATJJAFOS.js.map} +1 -1
  191. package/dist/{cron-ChQ6zcW2.d.ts → cron-Bx7tzm5R.d.ts} +54 -2
  192. package/dist/{cron-BdXOZco9.d.cts → cron-D-DVjGQe.d.cts} +54 -2
  193. package/dist/cron.cjs +33 -29
  194. package/dist/cron.d.cts +3 -3
  195. package/dist/cron.d.ts +3 -3
  196. package/dist/cron.js +32 -28
  197. package/dist/{errors-BUVjJGJA.d.cts → errors-DMY-gLSK.d.cts} +1 -1
  198. package/dist/{errors-CZIUKLHt.d.ts → errors-DjBQ4Tn8.d.ts} +1 -1
  199. package/dist/errors.cjs +21 -21
  200. package/dist/errors.d.cts +2 -2
  201. package/dist/errors.d.ts +2 -2
  202. package/dist/errors.js +2 -2
  203. package/dist/eval.cjs +41 -36
  204. package/dist/eval.cjs.map +1 -1
  205. package/dist/eval.js +37 -32
  206. package/dist/eval.js.map +1 -1
  207. package/dist/{executor-DPCBSI35.cjs → executor-BMRICN46.cjs} +26 -25
  208. package/dist/executor-BMRICN46.cjs.map +1 -0
  209. package/dist/{executor-ASDDIM2X.js → executor-T65PPOPT.js} +10 -9
  210. package/dist/executor-T65PPOPT.js.map +1 -0
  211. package/dist/filesystem/index.cjs +7 -7
  212. package/dist/filesystem/index.js +3 -3
  213. package/dist/fs-session-store-J5MCFFUM.cjs +19 -0
  214. package/dist/{fs-session-store-T5ZLQX42.cjs.map → fs-session-store-J5MCFFUM.cjs.map} +1 -1
  215. package/dist/fs-session-store-O6FNHECD.js +10 -0
  216. package/dist/{fs-session-store-K5QUPNJZ.js.map → fs-session-store-O6FNHECD.js.map} +1 -1
  217. package/dist/generate-object-UF6WIZLF.cjs +20 -0
  218. package/dist/{generate-object-F56VIZ6U.cjs.map → generate-object-UF6WIZLF.cjs.map} +1 -1
  219. package/dist/generate-object-XDCBYVK3.js +7 -0
  220. package/dist/{generate-object-LPSO6GVW.js.map → generate-object-XDCBYVK3.js.map} +1 -1
  221. package/dist/index-manager-N7RQYUKT.cjs +20 -0
  222. package/dist/{index-manager-DBJ55ZSO.cjs.map → index-manager-N7RQYUKT.cjs.map} +1 -1
  223. package/dist/index-manager-ZVZUHPP7.js +11 -0
  224. package/dist/{index-manager-F2H2RCZU.js.map → index-manager-ZVZUHPP7.js.map} +1 -1
  225. package/dist/index.cjs +138 -132
  226. package/dist/index.cjs.map +1 -1
  227. package/dist/index.d.cts +167 -9
  228. package/dist/index.d.ts +167 -9
  229. package/dist/index.js +47 -44
  230. package/dist/index.js.map +1 -1
  231. package/dist/{inject-session-RKNLUE72.js → inject-session-GQMTDZUN.js} +7 -6
  232. package/dist/inject-session-GQMTDZUN.js.map +1 -0
  233. package/dist/{inject-session-25EC74WV.cjs → inject-session-LFCYVSLJ.cjs} +9 -8
  234. package/dist/inject-session-LFCYVSLJ.cjs.map +1 -0
  235. package/dist/internal/agent-loop/loop-thinking-steps.d.ts +28 -0
  236. package/dist/internal/agent-loop/message-builders.d.ts +12 -3
  237. package/dist/internal/diagnostics.d.ts +24 -11
  238. package/dist/internal/llm/anthropic-shared.d.ts +4 -4
  239. package/dist/internal/llm/types.d.ts +49 -9
  240. package/dist/internal/local-agent/mcp-pool.d.ts +7 -3
  241. package/dist/internal/memory/adapters/azure-openai-embedding.d.cts +2 -0
  242. package/dist/internal/memory/adapters/catalog.d.cts +1 -0
  243. package/dist/internal/memory/adapters/cohere-embedding.d.cts +2 -0
  244. package/dist/internal/memory/adapters/deepinfra-embedding.d.cts +2 -0
  245. package/dist/internal/memory/adapters/gemini-embedding.d.cts +2 -0
  246. package/dist/internal/memory/adapters/index.cjs +28 -0
  247. package/dist/internal/memory/adapters/index.cjs.map +1 -0
  248. package/dist/internal/memory/adapters/index.d.cts +16 -0
  249. package/dist/internal/memory/adapters/index.d.ts +16 -0
  250. package/dist/internal/memory/adapters/index.js +11 -0
  251. package/dist/internal/memory/adapters/index.js.map +1 -0
  252. package/dist/internal/memory/adapters/jina-embedding.d.cts +2 -0
  253. package/dist/internal/memory/adapters/mistral-embedding.d.cts +2 -0
  254. package/dist/internal/memory/adapters/ollama-embedding.d.cts +34 -0
  255. package/dist/internal/memory/adapters/openai-compatible.d.cts +51 -0
  256. package/dist/internal/memory/adapters/openai-compatible.d.ts +28 -0
  257. package/dist/internal/memory/adapters/openai-embedding.d.cts +2 -0
  258. package/dist/internal/memory/adapters/openrouter-embedding.d.cts +2 -0
  259. package/dist/internal/memory/adapters/voyage-embedding.d.cts +2 -0
  260. package/dist/internal/memory/dreaming/diary.d.ts +4 -0
  261. package/dist/internal/memory/dreaming/phases.d.ts +15 -0
  262. package/dist/internal/memory/dreaming/run.d.ts +10 -0
  263. package/dist/internal/memory/migrate-sqlite-to-lance.d.ts +15 -0
  264. package/dist/internal/memory/sdk-memory-peer-loader.d.ts +21 -0
  265. package/dist/internal/persistence/index.cjs +25 -25
  266. package/dist/internal/persistence/index.js +6 -6
  267. package/dist/internal/persistence/session-transcript.d.cts +6 -0
  268. package/dist/internal/persistence/session-transcript.d.ts +6 -0
  269. package/dist/internal/runtime/concurrency/subagent-credentials.d.ts +35 -0
  270. package/dist/internal/security/index.cjs +13 -13
  271. package/dist/internal/security/index.js +3 -3
  272. package/dist/internal/session/agent-session-store.d.ts +1 -0
  273. package/dist/internal/session/session-types.d.ts +6 -1
  274. package/dist/judge-call-NA2G6ZMJ.js +5 -0
  275. package/dist/{judge-call-3S3T6O2Z.js.map → judge-call-NA2G6ZMJ.js.map} +1 -1
  276. package/dist/judge-call-U2D33JOW.cjs +22 -0
  277. package/dist/{judge-call-XIQJ5GIE.cjs.map → judge-call-U2D33JOW.cjs.map} +1 -1
  278. package/dist/models.cjs +20 -20
  279. package/dist/models.js +5 -5
  280. package/dist/path-safety.cjs +10 -10
  281. package/dist/path-safety.js +3 -3
  282. package/dist/persistence.cjs +35 -35
  283. package/dist/persistence.js +7 -7
  284. package/dist/project.cjs +5 -5
  285. package/dist/project.js +3 -3
  286. package/dist/registry-CAS6Y5ZY.js +9 -0
  287. package/dist/{registry-KMI5RA22.js.map → registry-CAS6Y5ZY.js.map} +1 -1
  288. package/dist/registry-JSDI4WKA.cjs +46 -0
  289. package/dist/{registry-BA3SLAN7.cjs.map → registry-JSDI4WKA.cjs.map} +1 -1
  290. package/dist/retry.cjs +4 -4
  291. package/dist/retry.js +3 -3
  292. package/dist/{run-vJHg2eGw.d.cts → run-i2-fUohR.d.cts} +16 -0
  293. package/dist/{run-vJHg2eGw.d.ts → run-i2-fUohR.d.ts} +16 -0
  294. package/dist/sandbox/index.cjs +6 -6
  295. package/dist/sandbox/index.js +2 -2
  296. package/dist/server/errors-envelope.cjs +14 -14
  297. package/dist/server/errors-envelope.d.cts +3 -3
  298. package/dist/server/errors-envelope.d.ts +3 -3
  299. package/dist/server/errors-envelope.js +3 -3
  300. package/dist/session-transcript-3B52DKTG.js +5 -0
  301. package/dist/{session-transcript-MMPWCESR.js.map → session-transcript-3B52DKTG.js.map} +1 -1
  302. package/dist/session-transcript-H7NUFXXM.cjs +50 -0
  303. package/dist/{session-transcript-DFGX6WNL.cjs.map → session-transcript-H7NUFXXM.cjs.map} +1 -1
  304. package/dist/skills.cjs +7 -7
  305. package/dist/skills.js +5 -5
  306. package/dist/stream-object-4FDU76YW.cjs +20 -0
  307. package/dist/{stream-object-YPXZ4F5P.cjs.map → stream-object-4FDU76YW.cjs.map} +1 -1
  308. package/dist/stream-object-HWDEEQN4.js +7 -0
  309. package/dist/{stream-object-AFERZU63.js.map → stream-object-HWDEEQN4.js.map} +1 -1
  310. package/dist/subagents-loader-A4W6C3QP.cjs +15 -0
  311. package/dist/subagents-loader-A4W6C3QP.cjs.map +1 -0
  312. package/dist/subagents-loader-X33KH2SZ.js +6 -0
  313. package/dist/subagents-loader-X33KH2SZ.js.map +1 -0
  314. package/dist/subagents-loader.cjs +6 -6
  315. package/dist/subagents-loader.d.cts +2 -2
  316. package/dist/subagents-loader.d.ts +2 -2
  317. package/dist/subagents-loader.js +4 -4
  318. package/dist/subscription/index.cjs +3 -3
  319. package/dist/subscription/index.js +2 -2
  320. package/dist/task-store.cjs +7 -7
  321. package/dist/task-store.js +4 -4
  322. package/dist/types/agent.d.ts +68 -3
  323. package/dist/types/conversation.d.ts +7 -0
  324. package/dist/types/messages.d.ts +9 -0
  325. package/dist/types/session-message.d.ts +59 -0
  326. package/dist/types/workflow.d.ts +36 -0
  327. package/dist/workflow.cjs +27 -27
  328. package/dist/workflow.d.cts +17 -1
  329. package/dist/workflow.d.ts +17 -1
  330. package/dist/workflow.js +6 -6
  331. package/docs/harness-capability-map.md +22 -0
  332. package/package.json +11 -1
  333. package/dist/agent-2GZC4W2A.cjs +0 -51
  334. package/dist/agent-3H3UKD6U.js +0 -42
  335. package/dist/batch-LXSALQC3.js.map +0 -1
  336. package/dist/batch-NZGN6SFV.cjs.map +0 -1
  337. package/dist/chunk-3BSP7LSG.cjs.map +0 -1
  338. package/dist/chunk-4APWS2YF.js.map +0 -1
  339. package/dist/chunk-6OKPJZMX.cjs.map +0 -1
  340. package/dist/chunk-6ZGD7R27.cjs.map +0 -1
  341. package/dist/chunk-A4XXV2C6.js.map +0 -1
  342. package/dist/chunk-A6GXYF2Q.js.map +0 -1
  343. package/dist/chunk-ACHGT3D2.js.map +0 -1
  344. package/dist/chunk-AOZYORH7.js.map +0 -1
  345. package/dist/chunk-BE3W4HYV.cjs.map +0 -1
  346. package/dist/chunk-BUGVDCI5.cjs.map +0 -1
  347. package/dist/chunk-FV3YEMQ7.js.map +0 -1
  348. package/dist/chunk-G2F67XUR.cjs.map +0 -1
  349. package/dist/chunk-G7X2Y7Y2.cjs.map +0 -1
  350. package/dist/chunk-HI6G3SNY.js.map +0 -1
  351. package/dist/chunk-IBDE4R5L.cjs.map +0 -1
  352. package/dist/chunk-KCZW75PI.js.map +0 -1
  353. package/dist/chunk-OFWU6UKF.cjs.map +0 -1
  354. package/dist/chunk-UZBA6YYP.cjs.map +0 -1
  355. package/dist/chunk-VUDH4D2M.js.map +0 -1
  356. package/dist/chunk-XS7SKY2F.js.map +0 -1
  357. package/dist/compact-session-RR3ILTES.js +0 -17
  358. package/dist/compact-session-YOWJJPPB.cjs +0 -54
  359. package/dist/context-Q6ISOCN2.cjs +0 -22
  360. package/dist/context-ZDBBPIHY.js +0 -5
  361. package/dist/executor-ASDDIM2X.js.map +0 -1
  362. package/dist/executor-DPCBSI35.cjs.map +0 -1
  363. package/dist/fs-session-store-K5QUPNJZ.js +0 -10
  364. package/dist/fs-session-store-T5ZLQX42.cjs +0 -19
  365. package/dist/generate-object-F56VIZ6U.cjs +0 -20
  366. package/dist/generate-object-LPSO6GVW.js +0 -7
  367. package/dist/index-manager-DBJ55ZSO.cjs +0 -19
  368. package/dist/index-manager-F2H2RCZU.js +0 -10
  369. package/dist/inject-session-25EC74WV.cjs.map +0 -1
  370. package/dist/inject-session-RKNLUE72.js.map +0 -1
  371. package/dist/judge-call-3S3T6O2Z.js +0 -5
  372. package/dist/judge-call-XIQJ5GIE.cjs +0 -22
  373. package/dist/registry-BA3SLAN7.cjs +0 -46
  374. package/dist/registry-KMI5RA22.js +0 -9
  375. package/dist/session-transcript-DFGX6WNL.cjs +0 -50
  376. package/dist/session-transcript-MMPWCESR.js +0 -5
  377. package/dist/stream-object-AFERZU63.js +0 -7
  378. package/dist/stream-object-YPXZ4F5P.cjs +0 -20
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/internal/auth/credential-store.ts","../src/internal/auth/oauth-engine.ts","../src/internal/auth/resolve-credential.ts"],"names":["fresh"],"mappings":"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","file":"chunk-JI34KBNC.js","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport {\n chmodSync,\n closeSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { z } from \"zod\";\n\nimport { AuthenticationError } from \"../../errors.js\";\n\n/**\n * M42 — the SDK credential store. Promoted DOWN from agent-builder's hardened `agents/lib/credentials.ts`\n * (M37), generalized from a closed `openrouter|anthropic|openai` union to an open `provider: string` and\n * driven by a caller-supplied {@link CredentialStoreConfig} (no hardcoded `.agent-builder`/`auth.json` /\n * `AGENT_BUILDER_HOME`). The security-critical file mechanics are ported VERBATIM (ADR D3 of the M42 plan):\n * atomic O_EXCL + rename + fsync write, 0700/0600 mode gates, `env` is always a PARAMETER (never an ambient\n * `process.env` read). Contract SHAPE adapted from OpenCode's provider `auth.loader` (MIT © 2025 opencode).\n *\n * The env-precedence + key-prefix-inference + declared-provider rungs of the agent-builder resolver are\n * APP POLICY and deliberately stay UP in the consumer; this module owns only the on-disk store + the\n * `api|oauth` discriminated union. See {@link resolveCredential} (SDK) for the store-read + refresh path.\n *\n * @internal\n */\nimport type {\n CredentialStoreConfig,\n StoredCredential,\n StoredOAuthCredential,\n} from \"./auth-types.js\";\n\n/** The store directory, honoring an optional `homeEnvVar` override. */\nexport function credentialHome(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n const override = config.homeEnvVar !== undefined ? env[config.homeEnvVar]?.trim() : undefined;\n return override !== undefined && override.length > 0\n ? override\n : join(config.home, config.dirName);\n}\n\n/** The credential file path inside the (possibly overridden) store directory. */\nexport function authFilePath(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n return join(credentialHome(config, env), config.fileName);\n}\n\n/**\n * A credential problem the caller can act on. Never carries the key value.\n *\n * M78 — this used to extend bare `Error`, which quietly disabled classification for the entire auth\n * path: `isTransientError` is `err instanceof TheokitAgentError && err.isRetryable === true`\n * (`errors.ts:443`), so a credential failure could never be judged transient OR permanent. The\n * predicate was not \"forgotten\" downstream — it was unusable there by construction.\n *\n * Extending `AuthenticationError` is ADDITIVE: the class still exists, still reports\n * `name: \"CredentialError\"`, and every existing `instanceof CredentialError` stays true. It only\n * gains ancestors. `AuthenticationError` pins `isRetryable: false`, so gaining the ability to be\n * classified does NOT turn a revoked credential into a retry loop.\n *\n * The single reference does the same thing with one root type: Codex routes every domain failure\n * through `CodexErr` with `is_retryable()` as a method (`protocol/src/error.rs:176`), rather than\n * parallel classes extending the language's `Error`.\n */\nexport class CredentialError extends AuthenticationError {\n // Field, not an assignment in the constructor: `AuthenticationError.name` is `override readonly`\n // (`errors.ts:174`), so `this.name = …` does not compile. Caught by `tsc`, not by vitest — the\n // suite was green with the broken assignment because the transpiler strips the type.\n override readonly name: string = \"CredentialError\";\n}\n\n/**\n * The on-disk store — a discriminated union on `type` (OpenCode `Info` shape). A legacy file with NO\n * `type` (or `type: 'api'`) is the API-key variant — read unchanged, no migration. The `oauth` variant\n * carries the token pair + expiry.\n */\nconst apiFileSchema = z\n .object({\n type: z.literal(\"api\").optional(),\n provider: z.string().min(1).optional(),\n api_key: z.string(),\n })\n .strict();\n\nconst oauthFileSchema = z\n .object({\n type: z.literal(\"oauth\"),\n provider: z.string().min(1),\n access: z.string().min(1),\n refresh: z.string().min(1),\n expires: z.number(),\n account_id: z.string().optional(),\n })\n .strict();\n\n// oauth first (it requires `type: 'oauth'`); a legacy `{provider?, api_key}` falls through to api.\nconst fileSchema = z.union([oauthFileSchema, apiFileSchema]);\n\n/**\n * Read the credential file. Absent ⇒ `undefined` (the normal case). Present-but-wrong is a typed error\n * naming the file: a malformed credential store must not surface as a raw parse crash. Enforces the\n * 0700 dir / 0600 file mode gates (ported verbatim — a writable dir lets an attacker swap the file for a\n * symlink to their own account).\n */\n/**\n * The 0700-dir / 0600-file mode gates (ported verbatim). The DIRECTORY matters as much as the file:\n * `mkdirSync(mode)` applies only at creation, so a pre-existing store dir keeps whatever mode it had, and a\n * writable dir lets an attacker replace the credential file with a symlink to their own 0600 file — the\n * agent then runs on THEIR account.\n */\nfunction assertSecureModes(dirPath: string, path: string): void {\n const dirMode = statSync(dirPath).mode & 0o777;\n if ((dirMode & 0o022) !== 0) {\n throw new CredentialError(\n `${dirPath} is writable by other users (mode ${dirMode.toString(8)}), so the credential file ` +\n `inside it can be replaced. Fix it with: chmod 700 ${dirPath}`,\n );\n }\n const mode = statSync(path).mode & 0o777;\n if ((mode & 0o077) !== 0) {\n throw new CredentialError(\n `${path} is readable by other users (mode ${mode.toString(8)}). ` +\n `A credential file must not be. Fix it with: chmod 600 ${path}`,\n );\n }\n}\n\n/**\n * A `z.union` reports a generic \"Invalid input\" at the root, hiding WHAT is wrong. Pick the sub-schema the\n * file was CLEARLY aiming at (by its `type` discriminant) and surface that schema's specific issue.\n */\nfunction describeUnionError(parsed: unknown, err: unknown, path: string): CredentialError {\n const looksOAuth =\n typeof parsed === \"object\" &&\n parsed !== null &&\n (parsed as { type?: unknown }).type === \"oauth\";\n const specific = looksOAuth ? oauthFileSchema.safeParse(parsed) : apiFileSchema.safeParse(parsed);\n let issue: z.ZodIssue | undefined;\n if (!specific.success) {\n issue = specific.error.issues[0];\n } else if (err instanceof z.ZodError) {\n issue = err.issues[0];\n }\n return new CredentialError(\n `${path}: ${issue?.message ?? String(err)} [${issue?.path.join(\".\") || \"root\"}]`,\n );\n}\n\n/** Parse the raw file into the store union, surfacing the SPECIFIC sub-schema issue (not a generic union error). */\nfunction parseStoredFile(raw: string, path: string): StoredCredential {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n // The parser's message embeds a snippet of the INPUT — up to the raw key when a user pastes the bare\n // key instead of JSON. The position is not actionable anyway, so the expected shape is more useful.\n throw new CredentialError(\n `${path} is not valid JSON. Expected: {\"provider\": \"<name>\", \"api_key\": \"...\"}`,\n );\n }\n try {\n return fileSchema.parse(parsed);\n } catch (err) {\n throw describeUnionError(parsed, err, path);\n }\n}\n\nexport function readAuthFile(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): StoredCredential | undefined {\n const path = authFilePath(config, env);\n\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw new CredentialError(`cannot read ${path}: ${(err as Error).message}`);\n }\n\n assertSecureModes(credentialHome(config, env), path);\n return parseStoredFile(raw, path);\n}\n\n/**\n * Read the stored OAuth credential (with its refresh token), or `undefined` when the store is absent or\n * holds an api credential. The oauth engine needs the refresh token, which the resolved bearer does not\n * carry. Enforces the same 0600/0700 gates as every other read.\n */\nexport function readStoredOAuth(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): StoredOAuthCredential | undefined {\n const stored = readAuthFile(config, env);\n return stored !== undefined && stored.type === \"oauth\" ? stored : undefined;\n}\n\n/** Narrows a writable credential to the oauth variant. */\nfunction isOAuthWrite(\n c: { provider: string; apiKey: string } | StoredOAuthCredential,\n): c is StoredOAuthCredential {\n return \"type\" in c && c.type === \"oauth\";\n}\n\n/**\n * Persist a credential atomically at mode `0600`. Ported VERBATIM (ADR D3): write to a random-named temp\n * file in the same directory with `wx` (O_EXCL), fsync, close, chmod, then `rename` (atomic on POSIX) —\n * so a crash mid-write leaves whatever was there untouched, and a pre-planted symlink cannot capture the\n * key. The api variant persists the unchanged `{provider, api_key}` (back-compat, no `type` key); the\n * oauth variant persists `{type:'oauth', provider, access, refresh, expires, account_id?}`.\n */\n/** Build the on-disk JSON payload for the credential variant, validating non-empty tokens. */\nfunction buildStorePayload(\n cred: { provider: string; apiKey: string } | StoredOAuthCredential,\n): Record<string, unknown> {\n if (isOAuthWrite(cred)) {\n if (cred.access.length === 0 || cred.refresh.length === 0) {\n throw new CredentialError(\n \"refusing to write an oauth credential with an empty access/refresh token\",\n );\n }\n return {\n type: \"oauth\",\n provider: cred.provider,\n access: cred.access,\n refresh: cred.refresh,\n expires: cred.expires,\n ...(cred.account_id !== undefined ? { account_id: cred.account_id } : {}),\n };\n }\n if (typeof cred.apiKey !== \"string\" || cred.apiKey.length === 0) {\n throw new CredentialError(\"refusing to write an empty API key\");\n }\n return { provider: cred.provider, api_key: cred.apiKey };\n}\n\nexport function writeCredential(\n cred: { provider: string; apiKey: string } | StoredOAuthCredential,\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n const payload = buildStorePayload(cred);\n\n const dir = credentialHome(config, env);\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n chmodSync(dir, 0o700); // unconditional: mkdirSync's mode applies only at creation\n\n const path = authFilePath(config, env);\n // RANDOM name + `wx` (O_EXCL): a predictable temp name with a plain write follows a pre-planted SYMLINK,\n // landing the key in an attacker's file while reporting success. O_EXCL refuses any pre-existing file or\n // link; the random suffix also removes the pid collision two containers sharing a bind-mounted home make.\n const tmp = `${path}.tmp-${randomBytes(8).toString(\"hex\")}`;\n try {\n const fd = openSync(tmp, \"wx\", 0o600);\n try {\n writeFileSync(fd, `${JSON.stringify(payload, null, 2)}\\n`);\n fsyncSync(fd);\n } finally {\n closeSync(fd);\n }\n chmodSync(tmp, 0o600); // explicit: the mode argument is subject to umask\n renameSync(tmp, path);\n } catch (err) {\n try {\n unlinkSync(tmp);\n } catch {\n // the temp file may not exist; its absence is not a failure of the write\n }\n throw new CredentialError(`cannot write ${path}: ${(err as Error).message}`);\n }\n return path;\n}\n","/**\n * M42 — the SDK OAuth engine. Promoted DOWN from agent-builder's hardened `agents/lib/oauth.ts` +\n * `oauth-device.ts` (M37), generalized to `provider: string` + a caller-supplied {@link CredentialStoreConfig}\n * (no hardcoded client IDs — the caller declares its provider's endpoints). Ported VERBATIM (ADR D3): the\n * refresh coalescing lock, the no-token-in-error discipline, and the RFC 8628 device grant.\n *\n * Reuses the SDK's typed error taxonomy (`AuthCallbackError` from `server/auth`) for exchange/refresh\n * failures. All network I/O + clock + sleep are INJECTED so the flow is deterministic.\n *\n * ─── ADAPTED FROM OpenCode (MIT License, Copyright (c) 2025 opencode — https://github.com/sst/opencode) ───\n * - the device-grant poll loop (device_code → authorization_pending / slow_down) is adapted from\n * `packages/opencode/src/plugin/github-copilot/copilot.ts`;\n * - the JWT-claim / account-id extraction + the OpenAI two-step headless flow are adapted from\n * `packages/opencode/src/plugin/openai/codex.ts`.\n * The MIT license permits this reuse with attribution; this notice + the NOTICE file are that attribution.\n *\n * @internal\n */\nimport { AuthCallbackError } from \"../../server/auth/errors.js\";\n\nimport type {\n CredentialStoreConfig,\n HttpDeps,\n OAuthProviderConfig,\n OAuthTokens,\n ResolvedCredential,\n} from \"./auth-types.js\";\nimport { authFilePath, readStoredOAuth, writeCredential } from \"./credential-store.js\";\n\n/** Refresh a token this many ms BEFORE it actually expires (avoid a last-second, mid-request expiry). */\nconst REFRESH_SKEW_MS = 60_000;\n\n/** Parse an OAuth token endpoint response into our token triple. Throws a typed error on a bad shape. */\nfunction parseTokenResponse(body: unknown, now: number): OAuthTokens {\n const b = body as {\n access_token?: unknown;\n refresh_token?: unknown;\n expires_in?: unknown;\n account_id?: unknown;\n };\n if (typeof b.access_token !== \"string\" || b.access_token.length === 0) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"token response had no access_token\",\n );\n }\n if (typeof b.refresh_token !== \"string\" || b.refresh_token.length === 0) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"token response had no refresh_token\",\n );\n }\n const expiresIn = typeof b.expires_in === \"number\" ? b.expires_in : 3600;\n return {\n access: b.access_token,\n refresh: b.refresh_token,\n expires: now + expiresIn * 1000,\n ...(typeof b.account_id === \"string\" ? { accountId: b.account_id } : {}),\n };\n}\n\n/** POST a form-encoded grant to the token endpoint; return the parsed JSON or throw a typed error. */\nasync function postGrant(\n config: OAuthProviderConfig,\n form: Record<string, string>,\n deps: HttpDeps,\n): Promise<OAuthTokens> {\n let res: Response;\n try {\n res = await deps.fetch(config.tokenEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\", accept: \"application/json\" },\n body: new URLSearchParams(form).toString(),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `token endpoint request failed: ${(err as Error).message}`,\n );\n }\n if (!res.ok) {\n // The body may carry an OAuth `error` code, but never echo it verbatim — it can contain a token in\n // some providers' error payloads. Report the status only.\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `token endpoint returned HTTP ${res.status}`,\n );\n }\n let json: unknown;\n try {\n json = await res.json();\n } catch {\n // Do NOT echo the parser message — on a 200 non-JSON body it embeds a snippet of the response, which\n // in a token context can contain access/refresh material.\n throw new AuthCallbackError(\"oauth_token_exchange_failed\", \"token response was not valid JSON\");\n }\n return parseTokenResponse(json, deps.now());\n}\n\n/** Exchange an authorization `code` (+ PKCE verifier) for the token pair. */\nexport function exchangeCode(\n config: OAuthProviderConfig,\n input: { code: string; verifier: string },\n deps: HttpDeps,\n): Promise<OAuthTokens> {\n return postGrant(\n config,\n {\n grant_type: \"authorization_code\",\n code: input.code,\n redirect_uri: config.redirectUri,\n client_id: config.clientId,\n code_verifier: input.verifier,\n },\n deps,\n );\n}\n\n/** Swap a refresh token for a fresh access (and possibly rotated refresh) token. */\nexport function refreshOAuthTokens(\n config: OAuthProviderConfig,\n refresh: string,\n deps: HttpDeps,\n): Promise<OAuthTokens> {\n return postGrant(\n config,\n { grant_type: \"refresh_token\", refresh_token: refresh, client_id: config.clientId },\n deps,\n );\n}\n\n/** Persist a token triple to the store's oauth variant through the hardened 0600 writer. */\nexport function persistOAuthTokens(\n provider: string,\n tokens: OAuthTokens,\n store: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n return writeCredential(\n {\n type: \"oauth\",\n provider,\n access: tokens.access,\n refresh: tokens.refresh,\n expires: tokens.expires,\n ...(tokens.accountId !== undefined ? { account_id: tokens.accountId } : {}),\n },\n store,\n env,\n );\n}\n\n/**\n * In-flight refreshes, keyed by the auth-file path. Refresh tokens ROTATE (single-use) on many providers,\n * so two concurrent turns must NOT both POST the same refresh token — the second would present an\n * already-consumed token and fail. This coalesces concurrent refreshes of the same store onto one promise.\n * Process-local — the single-credential store is per-user; a cross-process lock would be over-engineering.\n */\nconst inFlightRefresh = new Map<string, Promise<OAuthTokens>>();\n\n/**\n * Return a credential guaranteed fresh enough to use. An `api` credential passes through untouched. An\n * `oauth` credential still valid (beyond the skew window) passes through; an expired one is refreshed,\n * re-persisted 0600, and returned with the new access token. Concurrent refreshes of the same store are\n * coalesced (single-use refresh tokens); the rejected promise is evicted so a failure is not cached-poison.\n */\nexport async function ensureFreshCredential(\n resolved: ResolvedCredential,\n opts: {\n config: OAuthProviderConfig;\n store: CredentialStoreConfig;\n env?: Record<string, string | undefined>;\n },\n deps: HttpDeps,\n): Promise<ResolvedCredential> {\n if (resolved.kind !== \"oauth\") return resolved;\n\n const now = deps.now();\n if (resolved.expiresAt !== undefined && resolved.expiresAt > now + REFRESH_SKEW_MS) {\n return resolved; // still valid — no network, no rewrite\n }\n\n const env = opts.env ?? {};\n const path = authFilePath(opts.store, env);\n let refresh = inFlightRefresh.get(path);\n if (refresh === undefined) {\n refresh = (async (): Promise<OAuthTokens> => {\n const stored = readStoredOAuth(opts.store, env);\n if (stored === undefined) {\n // The resolved credential said oauth but the store no longer holds it — do not fabricate; surface it.\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"no stored oauth credential to refresh\",\n );\n }\n const fresh = await refreshOAuthTokens(opts.config, stored.refresh, deps);\n // M43 D4 fix #1 — the OAuth refresh response returns JWTs, not a top-level `account_id`, so\n // `parseTokenResponse` leaves `fresh.accountId` undefined. Prefer a freshly-derived id, else PRESERVE\n // the stored one (account_id is stable) — otherwise the Codex `ChatGPT-Account-Id` header empties after\n // the first refresh and the backend 401/403s.\n const merged: OAuthTokens = {\n ...fresh,\n accountId: fresh.accountId ?? stored.account_id,\n };\n persistOAuthTokens(resolved.provider, merged, opts.store, env);\n return merged;\n })();\n inFlightRefresh.set(path, refresh);\n refresh.finally(() => inFlightRefresh.delete(path)).catch(() => {});\n }\n\n const fresh = await refresh;\n return {\n kind: \"oauth\",\n provider: resolved.provider,\n apiKey: fresh.access,\n source: resolved.source,\n inferred: false,\n expiresAt: fresh.expires,\n };\n}\n","/**\n * M42 — `resolveCredential`: the public composition entrypoint over the credential store + oauth engine.\n * Given a provider name + a {@link CredentialStoreConfig} (and, for oauth, an {@link OAuthProviderConfig}),\n * read the store and return a FRESH `ResolvedCredential` — an api credential passes through by identity; an\n * oauth credential is transparently refreshed when its access token is within the skew window. Returns\n * `undefined` when the store holds no credential for `provider` (the caller then falls back to env / apiKeys).\n *\n * Mirrors agent-builder's `resolveFreshCredential` composition (store read → oauth → ensureFreshCredential),\n * defaulting `fetch`/`now` to globals. This is the async surface an oauth provider's M41 `transform.fetch`\n * calls at stream time, so a mid-turn token expiry refreshes without rebuilding the agent.\n *\n * @internal (re-exported from the package barrel as public)\n */\nimport type {\n CredentialStoreConfig,\n HttpDeps,\n OAuthProviderConfig,\n ResolvedCredential,\n} from \"./auth-types.js\";\nimport { authFilePath, readAuthFile } from \"./credential-store.js\";\nimport { ensureFreshCredential } from \"./oauth-engine.js\";\n\nexport interface ResolveCredentialOptions {\n /** The provider whose stored credential to resolve. */\n provider: string;\n /** Where the credential store lives. */\n store: CredentialStoreConfig;\n /** Env for the store's optional `homeEnvVar` override. Never an ambient read. */\n env?: Record<string, string | undefined>;\n /** Required to refresh an oauth credential; omit for an api-only store. */\n oauth?: OAuthProviderConfig;\n /** Injected HTTP + clock for deterministic tests; default globals. */\n deps?: { fetch?: typeof fetch; now?: () => number };\n}\n\n/**\n * Resolve a fresh credential for `provider` from the store, or `undefined` if the store holds none for it.\n * oauth credentials are auto-refreshed when `opts.oauth` is supplied; api credentials pass through.\n */\n/** Resolve (and, when a config is supplied, refresh) the oauth variant for the requested provider. */\nasync function resolveOAuth(\n stored: { provider: string; access: string; expires: number },\n path: string,\n opts: ResolveCredentialOptions,\n env: Record<string, string | undefined>,\n): Promise<ResolvedCredential | undefined> {\n if (stored.provider !== opts.provider) return undefined;\n const base: ResolvedCredential = {\n kind: \"oauth\",\n provider: opts.provider,\n apiKey: stored.access,\n source: path,\n inferred: false,\n expiresAt: stored.expires,\n };\n if (opts.oauth === undefined) return base; // no config to refresh with — return the stored access token\n const deps: HttpDeps = {\n fetch: opts.deps?.fetch ?? fetch,\n now: opts.deps?.now ?? (() => Date.now()),\n };\n return ensureFreshCredential(base, { config: opts.oauth, store: opts.store, env }, deps);\n}\n\nexport async function resolveCredential(\n opts: ResolveCredentialOptions,\n): Promise<ResolvedCredential | undefined> {\n const env = opts.env ?? {};\n const stored = readAuthFile(opts.store, env);\n if (stored === undefined) return undefined;\n\n const path = authFilePath(opts.store, env);\n\n if (stored.type === \"oauth\") {\n return resolveOAuth(stored, path, opts, env);\n }\n\n // api variant: require the stored `provider` to MATCH the requested provider (M42 review MEDIUM-2).\n // The generic SDK cannot infer a provider from a key prefix (that was agent-builder app policy), so a\n // provider-less or mismatched stored key is NOT attributed to the requested provider — otherwise a legacy\n // `{api_key:\"sk-ant-…\"}` file could be POSTed to the wrong vendor's endpoint (cross-vendor key exposure).\n // Fail-closed, mirroring OpenCode, whose credential resolution never attributes a key across providers.\n if (stored.api_key.length === 0) return undefined;\n if (stored.provider !== opts.provider) return undefined;\n return {\n kind: \"api\",\n provider: opts.provider,\n apiKey: stored.api_key,\n source: path,\n inferred: false,\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/internal/auth/credential-store.ts","../src/internal/auth/oauth-engine.ts","../src/internal/auth/resolve-credential.ts"],"names":["fresh"],"mappings":"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","file":"chunk-DKFGUOWL.js","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport {\n chmodSync,\n closeSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { z } from \"zod\";\n\nimport { AuthenticationError } from \"../../errors.js\";\n\n/**\n * M42 — the SDK credential store. Promoted DOWN from agent-builder's hardened `agents/lib/credentials.ts`\n * (M37), generalized from a closed `openrouter|anthropic|openai` union to an open `provider: string` and\n * driven by a caller-supplied {@link CredentialStoreConfig} (no hardcoded `.agent-builder`/`auth.json` /\n * `AGENT_BUILDER_HOME`). The security-critical file mechanics are ported VERBATIM (ADR D3 of the M42 plan):\n * atomic O_EXCL + rename + fsync write, 0700/0600 mode gates, `env` is always a PARAMETER (never an ambient\n * `process.env` read). Contract SHAPE adapted from OpenCode's provider `auth.loader` (MIT © 2025 opencode).\n *\n * The env-precedence + key-prefix-inference + declared-provider rungs of the agent-builder resolver are\n * APP POLICY and deliberately stay UP in the consumer; this module owns only the on-disk store + the\n * `api|oauth` discriminated union. See {@link resolveCredential} (SDK) for the store-read + refresh path.\n *\n * @internal\n */\nimport type {\n CredentialStoreConfig,\n StoredCredential,\n StoredOAuthCredential,\n} from \"./auth-types.js\";\n\n/** The store directory, honoring an optional `homeEnvVar` override. */\nexport function credentialHome(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n const override = config.homeEnvVar !== undefined ? env[config.homeEnvVar]?.trim() : undefined;\n return override !== undefined && override.length > 0\n ? override\n : join(config.home, config.dirName);\n}\n\n/** The credential file path inside the (possibly overridden) store directory. */\nexport function authFilePath(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n return join(credentialHome(config, env), config.fileName);\n}\n\n/**\n * A credential problem the caller can act on. Never carries the key value.\n *\n * M78 — this used to extend bare `Error`, which quietly disabled classification for the entire auth\n * path: `isTransientError` is `err instanceof TheokitAgentError && err.isRetryable === true`\n * (`errors.ts:443`), so a credential failure could never be judged transient OR permanent. The\n * predicate was not \"forgotten\" downstream — it was unusable there by construction.\n *\n * Extending `AuthenticationError` is ADDITIVE: the class still exists, still reports\n * `name: \"CredentialError\"`, and every existing `instanceof CredentialError` stays true. It only\n * gains ancestors. `AuthenticationError` pins `isRetryable: false`, so gaining the ability to be\n * classified does NOT turn a revoked credential into a retry loop.\n *\n * The single reference does the same thing with one root type: Codex routes every domain failure\n * through `CodexErr` with `is_retryable()` as a method (`protocol/src/error.rs:176`), rather than\n * parallel classes extending the language's `Error`.\n */\nexport class CredentialError extends AuthenticationError {\n // Field, not an assignment in the constructor: `AuthenticationError.name` is `override readonly`\n // (`errors.ts:174`), so `this.name = …` does not compile. Caught by `tsc`, not by vitest — the\n // suite was green with the broken assignment because the transpiler strips the type.\n override readonly name: string = \"CredentialError\";\n}\n\n/**\n * The on-disk store — a discriminated union on `type` (OpenCode `Info` shape). A legacy file with NO\n * `type` (or `type: 'api'`) is the API-key variant — read unchanged, no migration. The `oauth` variant\n * carries the token pair + expiry.\n */\nconst apiFileSchema = z\n .object({\n type: z.literal(\"api\").optional(),\n provider: z.string().min(1).optional(),\n api_key: z.string(),\n })\n .strict();\n\nconst oauthFileSchema = z\n .object({\n type: z.literal(\"oauth\"),\n provider: z.string().min(1),\n access: z.string().min(1),\n refresh: z.string().min(1),\n expires: z.number(),\n account_id: z.string().optional(),\n })\n .strict();\n\n// oauth first (it requires `type: 'oauth'`); a legacy `{provider?, api_key}` falls through to api.\nconst fileSchema = z.union([oauthFileSchema, apiFileSchema]);\n\n/**\n * Read the credential file. Absent ⇒ `undefined` (the normal case). Present-but-wrong is a typed error\n * naming the file: a malformed credential store must not surface as a raw parse crash. Enforces the\n * 0700 dir / 0600 file mode gates (ported verbatim — a writable dir lets an attacker swap the file for a\n * symlink to their own account).\n */\n/**\n * The 0700-dir / 0600-file mode gates (ported verbatim). The DIRECTORY matters as much as the file:\n * `mkdirSync(mode)` applies only at creation, so a pre-existing store dir keeps whatever mode it had, and a\n * writable dir lets an attacker replace the credential file with a symlink to their own 0600 file — the\n * agent then runs on THEIR account.\n */\nfunction assertSecureModes(dirPath: string, path: string): void {\n const dirMode = statSync(dirPath).mode & 0o777;\n if ((dirMode & 0o022) !== 0) {\n throw new CredentialError(\n `${dirPath} is writable by other users (mode ${dirMode.toString(8)}), so the credential file ` +\n `inside it can be replaced. Fix it with: chmod 700 ${dirPath}`,\n );\n }\n const mode = statSync(path).mode & 0o777;\n if ((mode & 0o077) !== 0) {\n throw new CredentialError(\n `${path} is readable by other users (mode ${mode.toString(8)}). ` +\n `A credential file must not be. Fix it with: chmod 600 ${path}`,\n );\n }\n}\n\n/**\n * A `z.union` reports a generic \"Invalid input\" at the root, hiding WHAT is wrong. Pick the sub-schema the\n * file was CLEARLY aiming at (by its `type` discriminant) and surface that schema's specific issue.\n */\nfunction describeUnionError(parsed: unknown, err: unknown, path: string): CredentialError {\n const looksOAuth =\n typeof parsed === \"object\" &&\n parsed !== null &&\n (parsed as { type?: unknown }).type === \"oauth\";\n const specific = looksOAuth ? oauthFileSchema.safeParse(parsed) : apiFileSchema.safeParse(parsed);\n let issue: z.ZodIssue | undefined;\n if (!specific.success) {\n issue = specific.error.issues[0];\n } else if (err instanceof z.ZodError) {\n issue = err.issues[0];\n }\n return new CredentialError(\n `${path}: ${issue?.message ?? String(err)} [${issue?.path.join(\".\") || \"root\"}]`,\n );\n}\n\n/** Parse the raw file into the store union, surfacing the SPECIFIC sub-schema issue (not a generic union error). */\nfunction parseStoredFile(raw: string, path: string): StoredCredential {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n // The parser's message embeds a snippet of the INPUT — up to the raw key when a user pastes the bare\n // key instead of JSON. The position is not actionable anyway, so the expected shape is more useful.\n throw new CredentialError(\n `${path} is not valid JSON. Expected: {\"provider\": \"<name>\", \"api_key\": \"...\"}`,\n );\n }\n try {\n return fileSchema.parse(parsed);\n } catch (err) {\n throw describeUnionError(parsed, err, path);\n }\n}\n\nexport function readAuthFile(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): StoredCredential | undefined {\n const path = authFilePath(config, env);\n\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw new CredentialError(`cannot read ${path}: ${(err as Error).message}`);\n }\n\n assertSecureModes(credentialHome(config, env), path);\n return parseStoredFile(raw, path);\n}\n\n/**\n * Read the stored OAuth credential (with its refresh token), or `undefined` when the store is absent or\n * holds an api credential. The oauth engine needs the refresh token, which the resolved bearer does not\n * carry. Enforces the same 0600/0700 gates as every other read.\n */\nexport function readStoredOAuth(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): StoredOAuthCredential | undefined {\n const stored = readAuthFile(config, env);\n return stored !== undefined && stored.type === \"oauth\" ? stored : undefined;\n}\n\n/** Narrows a writable credential to the oauth variant. */\nfunction isOAuthWrite(\n c: { provider: string; apiKey: string } | StoredOAuthCredential,\n): c is StoredOAuthCredential {\n return \"type\" in c && c.type === \"oauth\";\n}\n\n/**\n * Persist a credential atomically at mode `0600`. Ported VERBATIM (ADR D3): write to a random-named temp\n * file in the same directory with `wx` (O_EXCL), fsync, close, chmod, then `rename` (atomic on POSIX) —\n * so a crash mid-write leaves whatever was there untouched, and a pre-planted symlink cannot capture the\n * key. The api variant persists the unchanged `{provider, api_key}` (back-compat, no `type` key); the\n * oauth variant persists `{type:'oauth', provider, access, refresh, expires, account_id?}`.\n */\n/** Build the on-disk JSON payload for the credential variant, validating non-empty tokens. */\nfunction buildStorePayload(\n cred: { provider: string; apiKey: string } | StoredOAuthCredential,\n): Record<string, unknown> {\n if (isOAuthWrite(cred)) {\n if (cred.access.length === 0 || cred.refresh.length === 0) {\n throw new CredentialError(\n \"refusing to write an oauth credential with an empty access/refresh token\",\n );\n }\n return {\n type: \"oauth\",\n provider: cred.provider,\n access: cred.access,\n refresh: cred.refresh,\n expires: cred.expires,\n ...(cred.account_id !== undefined ? { account_id: cred.account_id } : {}),\n };\n }\n if (typeof cred.apiKey !== \"string\" || cred.apiKey.length === 0) {\n throw new CredentialError(\"refusing to write an empty API key\");\n }\n return { provider: cred.provider, api_key: cred.apiKey };\n}\n\nexport function writeCredential(\n cred: { provider: string; apiKey: string } | StoredOAuthCredential,\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n const payload = buildStorePayload(cred);\n\n const dir = credentialHome(config, env);\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n chmodSync(dir, 0o700); // unconditional: mkdirSync's mode applies only at creation\n\n const path = authFilePath(config, env);\n // RANDOM name + `wx` (O_EXCL): a predictable temp name with a plain write follows a pre-planted SYMLINK,\n // landing the key in an attacker's file while reporting success. O_EXCL refuses any pre-existing file or\n // link; the random suffix also removes the pid collision two containers sharing a bind-mounted home make.\n const tmp = `${path}.tmp-${randomBytes(8).toString(\"hex\")}`;\n try {\n const fd = openSync(tmp, \"wx\", 0o600);\n try {\n writeFileSync(fd, `${JSON.stringify(payload, null, 2)}\\n`);\n fsyncSync(fd);\n } finally {\n closeSync(fd);\n }\n chmodSync(tmp, 0o600); // explicit: the mode argument is subject to umask\n renameSync(tmp, path);\n } catch (err) {\n try {\n unlinkSync(tmp);\n } catch {\n // the temp file may not exist; its absence is not a failure of the write\n }\n throw new CredentialError(`cannot write ${path}: ${(err as Error).message}`);\n }\n return path;\n}\n","/**\n * M42 — the SDK OAuth engine. Promoted DOWN from agent-builder's hardened `agents/lib/oauth.ts` +\n * `oauth-device.ts` (M37), generalized to `provider: string` + a caller-supplied {@link CredentialStoreConfig}\n * (no hardcoded client IDs — the caller declares its provider's endpoints). Ported VERBATIM (ADR D3): the\n * refresh coalescing lock, the no-token-in-error discipline, and the RFC 8628 device grant.\n *\n * Reuses the SDK's typed error taxonomy (`AuthCallbackError` from `server/auth`) for exchange/refresh\n * failures. All network I/O + clock + sleep are INJECTED so the flow is deterministic.\n *\n * ─── ADAPTED FROM OpenCode (MIT License, Copyright (c) 2025 opencode — https://github.com/sst/opencode) ───\n * - the device-grant poll loop (device_code → authorization_pending / slow_down) is adapted from\n * `packages/opencode/src/plugin/github-copilot/copilot.ts`;\n * - the JWT-claim / account-id extraction + the OpenAI two-step headless flow are adapted from\n * `packages/opencode/src/plugin/openai/codex.ts`.\n * The MIT license permits this reuse with attribution; this notice + the NOTICE file are that attribution.\n *\n * @internal\n */\nimport { AuthCallbackError } from \"../../server/auth/errors.js\";\n\nimport type {\n CredentialStoreConfig,\n HttpDeps,\n OAuthProviderConfig,\n OAuthTokens,\n ResolvedCredential,\n} from \"./auth-types.js\";\nimport { authFilePath, readStoredOAuth, writeCredential } from \"./credential-store.js\";\n\n/** Refresh a token this many ms BEFORE it actually expires (avoid a last-second, mid-request expiry). */\nconst REFRESH_SKEW_MS = 60_000;\n\n/** Parse an OAuth token endpoint response into our token triple. Throws a typed error on a bad shape. */\nfunction parseTokenResponse(body: unknown, now: number): OAuthTokens {\n const b = body as {\n access_token?: unknown;\n refresh_token?: unknown;\n expires_in?: unknown;\n account_id?: unknown;\n };\n if (typeof b.access_token !== \"string\" || b.access_token.length === 0) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"token response had no access_token\",\n );\n }\n if (typeof b.refresh_token !== \"string\" || b.refresh_token.length === 0) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"token response had no refresh_token\",\n );\n }\n const expiresIn = typeof b.expires_in === \"number\" ? b.expires_in : 3600;\n return {\n access: b.access_token,\n refresh: b.refresh_token,\n expires: now + expiresIn * 1000,\n ...(typeof b.account_id === \"string\" ? { accountId: b.account_id } : {}),\n };\n}\n\n/** POST a form-encoded grant to the token endpoint; return the parsed JSON or throw a typed error. */\nasync function postGrant(\n config: OAuthProviderConfig,\n form: Record<string, string>,\n deps: HttpDeps,\n): Promise<OAuthTokens> {\n let res: Response;\n try {\n res = await deps.fetch(config.tokenEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\", accept: \"application/json\" },\n body: new URLSearchParams(form).toString(),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `token endpoint request failed: ${(err as Error).message}`,\n );\n }\n if (!res.ok) {\n // The body may carry an OAuth `error` code, but never echo it verbatim — it can contain a token in\n // some providers' error payloads. Report the status only.\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `token endpoint returned HTTP ${res.status}`,\n );\n }\n let json: unknown;\n try {\n json = await res.json();\n } catch {\n // Do NOT echo the parser message — on a 200 non-JSON body it embeds a snippet of the response, which\n // in a token context can contain access/refresh material.\n throw new AuthCallbackError(\"oauth_token_exchange_failed\", \"token response was not valid JSON\");\n }\n return parseTokenResponse(json, deps.now());\n}\n\n/** Exchange an authorization `code` (+ PKCE verifier) for the token pair. */\nexport function exchangeCode(\n config: OAuthProviderConfig,\n input: { code: string; verifier: string },\n deps: HttpDeps,\n): Promise<OAuthTokens> {\n return postGrant(\n config,\n {\n grant_type: \"authorization_code\",\n code: input.code,\n redirect_uri: config.redirectUri,\n client_id: config.clientId,\n code_verifier: input.verifier,\n },\n deps,\n );\n}\n\n/** Swap a refresh token for a fresh access (and possibly rotated refresh) token. */\nexport function refreshOAuthTokens(\n config: OAuthProviderConfig,\n refresh: string,\n deps: HttpDeps,\n): Promise<OAuthTokens> {\n return postGrant(\n config,\n { grant_type: \"refresh_token\", refresh_token: refresh, client_id: config.clientId },\n deps,\n );\n}\n\n/** Persist a token triple to the store's oauth variant through the hardened 0600 writer. */\nexport function persistOAuthTokens(\n provider: string,\n tokens: OAuthTokens,\n store: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n return writeCredential(\n {\n type: \"oauth\",\n provider,\n access: tokens.access,\n refresh: tokens.refresh,\n expires: tokens.expires,\n ...(tokens.accountId !== undefined ? { account_id: tokens.accountId } : {}),\n },\n store,\n env,\n );\n}\n\n/**\n * In-flight refreshes, keyed by the auth-file path. Refresh tokens ROTATE (single-use) on many providers,\n * so two concurrent turns must NOT both POST the same refresh token — the second would present an\n * already-consumed token and fail. This coalesces concurrent refreshes of the same store onto one promise.\n * Process-local — the single-credential store is per-user; a cross-process lock would be over-engineering.\n */\nconst inFlightRefresh = new Map<string, Promise<OAuthTokens>>();\n\n/**\n * Return a credential guaranteed fresh enough to use. An `api` credential passes through untouched. An\n * `oauth` credential still valid (beyond the skew window) passes through; an expired one is refreshed,\n * re-persisted 0600, and returned with the new access token. Concurrent refreshes of the same store are\n * coalesced (single-use refresh tokens); the rejected promise is evicted so a failure is not cached-poison.\n */\nexport async function ensureFreshCredential(\n resolved: ResolvedCredential,\n opts: {\n config: OAuthProviderConfig;\n store: CredentialStoreConfig;\n env?: Record<string, string | undefined>;\n },\n deps: HttpDeps,\n): Promise<ResolvedCredential> {\n if (resolved.kind !== \"oauth\") return resolved;\n\n const now = deps.now();\n if (resolved.expiresAt !== undefined && resolved.expiresAt > now + REFRESH_SKEW_MS) {\n return resolved; // still valid — no network, no rewrite\n }\n\n const env = opts.env ?? {};\n const path = authFilePath(opts.store, env);\n let refresh = inFlightRefresh.get(path);\n if (refresh === undefined) {\n refresh = (async (): Promise<OAuthTokens> => {\n const stored = readStoredOAuth(opts.store, env);\n if (stored === undefined) {\n // The resolved credential said oauth but the store no longer holds it — do not fabricate; surface it.\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"no stored oauth credential to refresh\",\n );\n }\n const fresh = await refreshOAuthTokens(opts.config, stored.refresh, deps);\n // M43 D4 fix #1 — the OAuth refresh response returns JWTs, not a top-level `account_id`, so\n // `parseTokenResponse` leaves `fresh.accountId` undefined. Prefer a freshly-derived id, else PRESERVE\n // the stored one (account_id is stable) — otherwise the Codex `ChatGPT-Account-Id` header empties after\n // the first refresh and the backend 401/403s.\n const merged: OAuthTokens = {\n ...fresh,\n accountId: fresh.accountId ?? stored.account_id,\n };\n persistOAuthTokens(resolved.provider, merged, opts.store, env);\n return merged;\n })();\n inFlightRefresh.set(path, refresh);\n refresh.finally(() => inFlightRefresh.delete(path)).catch(() => {});\n }\n\n const fresh = await refresh;\n return {\n kind: \"oauth\",\n provider: resolved.provider,\n apiKey: fresh.access,\n source: resolved.source,\n inferred: false,\n expiresAt: fresh.expires,\n };\n}\n","/**\n * M42 — `resolveCredential`: the public composition entrypoint over the credential store + oauth engine.\n * Given a provider name + a {@link CredentialStoreConfig} (and, for oauth, an {@link OAuthProviderConfig}),\n * read the store and return a FRESH `ResolvedCredential` — an api credential passes through by identity; an\n * oauth credential is transparently refreshed when its access token is within the skew window. Returns\n * `undefined` when the store holds no credential for `provider` (the caller then falls back to env / apiKeys).\n *\n * Mirrors agent-builder's `resolveFreshCredential` composition (store read → oauth → ensureFreshCredential),\n * defaulting `fetch`/`now` to globals. This is the async surface an oauth provider's M41 `transform.fetch`\n * calls at stream time, so a mid-turn token expiry refreshes without rebuilding the agent.\n *\n * @internal (re-exported from the package barrel as public)\n */\nimport type {\n CredentialStoreConfig,\n HttpDeps,\n OAuthProviderConfig,\n ResolvedCredential,\n} from \"./auth-types.js\";\nimport { authFilePath, readAuthFile } from \"./credential-store.js\";\nimport { ensureFreshCredential } from \"./oauth-engine.js\";\n\nexport interface ResolveCredentialOptions {\n /** The provider whose stored credential to resolve. */\n provider: string;\n /** Where the credential store lives. */\n store: CredentialStoreConfig;\n /** Env for the store's optional `homeEnvVar` override. Never an ambient read. */\n env?: Record<string, string | undefined>;\n /** Required to refresh an oauth credential; omit for an api-only store. */\n oauth?: OAuthProviderConfig;\n /** Injected HTTP + clock for deterministic tests; default globals. */\n deps?: { fetch?: typeof fetch; now?: () => number };\n}\n\n/**\n * Resolve a fresh credential for `provider` from the store, or `undefined` if the store holds none for it.\n * oauth credentials are auto-refreshed when `opts.oauth` is supplied; api credentials pass through.\n */\n/** Resolve (and, when a config is supplied, refresh) the oauth variant for the requested provider. */\nasync function resolveOAuth(\n stored: { provider: string; access: string; expires: number },\n path: string,\n opts: ResolveCredentialOptions,\n env: Record<string, string | undefined>,\n): Promise<ResolvedCredential | undefined> {\n if (stored.provider !== opts.provider) return undefined;\n const base: ResolvedCredential = {\n kind: \"oauth\",\n provider: opts.provider,\n apiKey: stored.access,\n source: path,\n inferred: false,\n expiresAt: stored.expires,\n };\n if (opts.oauth === undefined) return base; // no config to refresh with — return the stored access token\n const deps: HttpDeps = {\n fetch: opts.deps?.fetch ?? fetch,\n now: opts.deps?.now ?? (() => Date.now()),\n };\n return ensureFreshCredential(base, { config: opts.oauth, store: opts.store, env }, deps);\n}\n\nexport async function resolveCredential(\n opts: ResolveCredentialOptions,\n): Promise<ResolvedCredential | undefined> {\n const env = opts.env ?? {};\n const stored = readAuthFile(opts.store, env);\n if (stored === undefined) return undefined;\n\n const path = authFilePath(opts.store, env);\n\n if (stored.type === \"oauth\") {\n return resolveOAuth(stored, path, opts, env);\n }\n\n // api variant: require the stored `provider` to MATCH the requested provider (M42 review MEDIUM-2).\n // The generic SDK cannot infer a provider from a key prefix (that was agent-builder app policy), so a\n // provider-less or mismatched stored key is NOT attributed to the requested provider — otherwise a legacy\n // `{api_key:\"sk-ant-…\"}` file could be POSTed to the wrong vendor's endpoint (cross-vendor key exposure).\n // Fail-closed, mirroring OpenCode, whose credential resolution never attributes a key across providers.\n if (stored.api_key.length === 0) return undefined;\n if (stored.provider !== opts.provider) return undefined;\n return {\n kind: \"api\",\n provider: opts.provider,\n apiKey: stored.api_key,\n source: path,\n inferred: false,\n };\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkYLQQX5W2_cjs = require('./chunk-YLQQX5W2.cjs');
4
- var chunkBE3W4HYV_cjs = require('./chunk-BE3W4HYV.cjs');
4
+ var chunkBCQ3E2ZG_cjs = require('./chunk-BCQ3E2ZG.cjs');
5
5
  var fs = require('fs');
6
6
  var path = require('path');
7
7
 
@@ -16,7 +16,7 @@ async function getProperLockfile() {
16
16
  if (!validateLockModule(mod)) {
17
17
  if (!warnedStructural) {
18
18
  warnedStructural = true;
19
- chunkBE3W4HYV_cjs.diag(
19
+ chunkBCQ3E2ZG_cjs.diag(
20
20
  "[theokit-sdk] proper-lockfile: imported module does NOT expose the expected `lock`/`unlock` API surface. This may indicate a supply-chain compromise or an incompatible major version. Falling back to in-process mutex (no cross-process safety). Reinstall with: pnpm add proper-lockfile@^11\n"
21
21
  );
22
22
  }
@@ -39,7 +39,7 @@ async function withFileLock(path, fn, options) {
39
39
  if (lib === null) {
40
40
  if (!warnedMissing) {
41
41
  warnedMissing = true;
42
- chunkBE3W4HYV_cjs.diag(
42
+ chunkBCQ3E2ZG_cjs.diag(
43
43
  "[theokit-sdk] proper-lockfile not installed; cross-process file lock unavailable. Install with: pnpm add proper-lockfile\n"
44
44
  );
45
45
  }
@@ -166,5 +166,5 @@ exports.appendJsonl = appendJsonl;
166
166
  exports.loadJsonl = loadJsonl;
167
167
  exports.readJsonlIds = readJsonlIds;
168
168
  exports.withFileLock = withFileLock;
169
- //# sourceMappingURL=chunk-ZET34IZE.cjs.map
170
- //# sourceMappingURL=chunk-ZET34IZE.cjs.map
169
+ //# sourceMappingURL=chunk-DMTZ3FII.cjs.map
170
+ //# sourceMappingURL=chunk-DMTZ3FII.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/internal/persistence/file-lock.ts","../src/internal/persistence/jsonl.ts"],"names":["diag","withCwdMutex","readFileSync","path","mkdirSync","dirname","openSync","writeSync","closeSync","fstatSync","readSync"],"mappings":"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","file":"chunk-ZET34IZE.cjs","sourcesContent":["/**\n * Cross-process file lock helper (ADR D61).\n *\n * Uses `proper-lockfile` (optional peer dep) for cross-process locks. When\n * the peer dep is absent, falls back to `withCwdMutex` (in-process only)\n * with a one-shot stderr warning.\n *\n * EC-1 fix: uses a companion `<path>.lock` file with `realpath: false` so\n * `withFileLock` works even when the target `path` does not exist yet.\n * Without this, fresh installs that lock-then-create would crash with ENOENT.\n *\n * @internal\n */\n\nimport { diag } from \"../diagnostics.js\";\nimport { withCwdMutex } from \"./cwd-mutex.js\";\n\ninterface ProperLockfileModule {\n lock: (file: string, options: ProperLockfileOptions) => Promise<() => Promise<void>>;\n}\n\ninterface ProperLockfileOptions {\n lockfilePath?: string;\n realpath?: boolean;\n stale?: number;\n retries?: {\n retries: number;\n factor?: number;\n minTimeout?: number;\n maxTimeout?: number;\n };\n}\n\nlet cached: ProperLockfileModule | null | undefined;\nlet warnedMissing = false;\nlet warnedStructural = false;\n\nasync function getProperLockfile(): Promise<ProperLockfileModule | null> {\n if (cached !== undefined) return cached;\n try {\n const mod = await import(\"proper-lockfile\");\n // T5.9 — supply-chain hardening: validate the imported module\n // exposes the API surface we depend on BEFORE caching it. A\n // tampered or incompatible version that lacks `lock`/`unlock`\n // functions gets treated as \"not installed\" with an advisory\n // warning — never silently used.\n if (!validateLockModule(mod)) {\n if (!warnedStructural) {\n warnedStructural = true;\n diag(\n \"[theokit-sdk] proper-lockfile: imported module does NOT expose \" +\n \"the expected `lock`/`unlock` API surface. This may indicate a \" +\n \"supply-chain compromise or an incompatible major version. \" +\n \"Falling back to in-process mutex (no cross-process safety). \" +\n \"Reinstall with: pnpm add proper-lockfile@^11\\n\",\n );\n }\n cached = null;\n return cached;\n }\n cached = mod as ProperLockfileModule;\n } catch {\n cached = null;\n }\n return cached;\n}\n\n/**\n * T5.9 — Structural validation of the dynamically-imported\n * `proper-lockfile` module. Verifies the API surface we depend on\n * (`lock` and `unlock` as functions) is present. Pure function —\n * never throws, never mutates, never performs I/O.\n *\n * Exported via `__TESTING__validateLockModule` seam so unit tests\n * can drive the check without spinning up the dynamic import.\n *\n * @internal\n */\nfunction validateLockModule(mod: unknown): boolean {\n if (mod === null || mod === undefined || typeof mod !== \"object\") return false;\n const m = mod as Record<string, unknown>;\n return typeof m.lock === \"function\" && typeof m.unlock === \"function\";\n}\n\n/**\n * T5.9 — Test seam: expose the structural validator for unit tests.\n * NOT included in the public barrel.\n *\n * @internal\n */\nexport function __TESTING__validateLockModule(mod: unknown): boolean {\n return validateLockModule(mod);\n}\n\n/**\n * T5.9 — Test seam: reset the module cache + warning flags between\n * tests so each test starts fresh. NOT included in the public barrel.\n *\n * @internal\n */\nexport function __TESTING__resetFileLockCache(): void {\n cached = undefined;\n warnedMissing = false;\n warnedStructural = false;\n}\n\n/**\n * Options for `withFileLock`.\n *\n * @internal\n */\nexport interface FileLockOptions {\n /** Stale lock timeout in ms. Default 30_000 (30s). */\n stale?: number;\n /** Max retries on busy lock. Default 5. */\n retries?: number;\n /** Backoff factor between retries. Default 1.5. */\n retryFactor?: number;\n}\n\n/**\n * Run `fn` while holding an OS-level cross-process lock on `path`.\n *\n * If `proper-lockfile` is installed, uses it with a companion `<path>.lock`\n * file (`realpath: false`, so target file does NOT need to exist yet).\n * Otherwise falls back to in-process `withCwdMutex` and prints a one-shot\n * stderr warning telling the user to install `proper-lockfile` for\n * cross-process safety.\n *\n * The lock is released even when `fn` throws.\n *\n * @internal\n */\nexport async function withFileLock<T>(\n path: string,\n fn: () => Promise<T>,\n options?: FileLockOptions,\n): Promise<T> {\n const lib = await getProperLockfile();\n\n if (lib === null) {\n if (!warnedMissing) {\n warnedMissing = true;\n diag(\n \"[theokit-sdk] proper-lockfile not installed; \" +\n \"cross-process file lock unavailable. \" +\n \"Install with: pnpm add proper-lockfile\\n\",\n );\n }\n return withCwdMutex(`file-lock:${path}`, fn);\n }\n\n // proper-lockfile errors immediately on same-process concurrent acquire\n // (\"Lock file is already being held\"). Wrap with cwd-mutex first so\n // in-process callers queue and only ONE thread at a time enters the\n // cross-process acquire path. Combined: full in-process + cross-process\n // serialization.\n return withCwdMutex(`file-lock:${path}`, async () => {\n const release = await lib.lock(path, {\n // EC-1: companion lockfile, target path may not exist yet.\n lockfilePath: `${path}.lock`,\n realpath: false,\n stale: options?.stale ?? 30_000,\n retries: {\n retries: options?.retries ?? 5,\n factor: options?.retryFactor ?? 1.5,\n minTimeout: 100,\n maxTimeout: 5_000,\n },\n });\n\n try {\n return await fn();\n } finally {\n await release();\n }\n });\n}\n\n/**\n * Test helper — resets the cached proper-lockfile module + warning flag.\n * Allows tests to simulate \"module absent\" by clearing cache then\n * monkey-patching the dynamic import resolution.\n *\n * @internal\n */\nexport function _resetFileLockCacheForTesting(): void {\n cached = undefined;\n warnedMissing = false;\n}\n","/**\n * Durable JSONL primitives shared by the eval harness (M6).\n *\n * - `loadJsonl` — generic dataset reader (split/trim/skip-blank/parse) with a\n * line-numbered {@link JsonlParseError}. The dataset SCHEMA is the caller's\n * concern via `map` (M6 ADR D3) — this module owns only the parse.\n * - `appendJsonl` / `readJsonlIds` — crash-durable, resumable batch persistence\n * (M6 ADR D1): each record is appended as one whole `\\n`-terminated line the\n * instant it is produced, and a re-run resumes by skipping already-keyed rows.\n *\n * referencia: knowledge-base/references/theocode-eval/lib/swebench-dataset.ts:82\n * (parseJsonl + line-N error) and swebench-batch.ts:113,205 (resume + per-line\n * flush).\n *\n * @internal\n */\nimport {\n closeSync,\n fstatSync,\n mkdirSync,\n openSync,\n readFileSync,\n readSync,\n writeSync,\n} from \"node:fs\";\nimport { dirname } from \"node:path\";\n\n/** Raised when a JSONL line is not valid JSON or is not a JSON object. Carries the 1-based line number. */\nexport class JsonlParseError extends Error {\n constructor(\n message: string,\n readonly line: number,\n ) {\n super(message);\n this.name = \"JsonlParseError\";\n }\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Parse a single trimmed line to a plain object, or `undefined` if blank / invalid / non-object. */\nfunction tryParseObjectLine(line: string): Record<string, unknown> | undefined {\n if (line.length === 0) return undefined;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n return undefined;\n }\n return isPlainObject(parsed) ? parsed : undefined;\n}\n\n/**\n * Parse a JSONL file into rows. Blank lines are skipped. A malformed or\n * non-object line throws {@link JsonlParseError} naming the 1-based line. When\n * `map` is provided, each raw object is mapped to the typed row (the SWE-bench\n * schema lives in the caller's `map`, per M6 ADR D3).\n */\nexport function loadJsonl<T = Record<string, unknown>>(\n path: string,\n opts: {\n map?: (raw: Record<string, unknown>, lineNumber: number) => T;\n /**\n * M81 — tolerate a truncated LAST line (a crash artifact: the process died mid-write).\n *\n * Opt-in on purpose. As a default it would also swallow corruption in the MIDDLE of the file,\n * turning loud data loss into silent data loss — the wrong trade for a session store.\n */\n tolerateTrailingPartialLine?: boolean;\n } = {},\n): T[] {\n const lines = readFileSync(path, \"utf8\").split(\"\\n\");\n const out: T[] = [];\n for (let i = 0; i < lines.length; i += 1) {\n const lineNumber = i + 1;\n const line = (lines[i] ?? \"\").trim();\n if (line.length === 0) continue;\n // M81 — `undefined` = a tolerated invalid line (the last one, truncated by a crash). Any other\n // invalid line has already thrown inside `parseLine`.\n const parsed = parseLine(\n line,\n lineNumber,\n opts.tolerateTrailingPartialLine === true && lineNumber === lines.length,\n );\n if (parsed === undefined) break;\n out.push(opts.map ? opts.map(parsed, lineNumber) : (parsed as unknown as T));\n }\n return out;\n}\n\n/**\n * Parses ONE line, returning `undefined` when it is a tolerated truncated last line.\n *\n * Extracted because `loadJsonl` went over the cognitive-complexity ceiling once it gained the\n * tolerance — and because parsing a line and iterating a file are two responsibilities that were\n * only together out of habit.\n */\nfunction parseLine(\n line: string,\n lineNumber: number,\n tolerate: boolean,\n): Record<string, unknown> | undefined {\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n if (tolerate) return undefined;\n throw new JsonlParseError(`line ${lineNumber}: invalid JSON`, lineNumber);\n }\n if (!isPlainObject(parsed)) {\n throw new JsonlParseError(`line ${lineNumber}: not a JSON object`, lineNumber);\n }\n return parsed;\n}\n\n/**\n * Append one record as a whole `\\n`-terminated JSON line. Creates the parent dir\n * if missing. `appendFileSync` is synchronous, so within a single Node process\n * the event loop serializes writes and each call writes its line atomically —\n * interleave-safe for the bounded-concurrency batch runner.\n *\n * referencia: swebench-batch.ts:192 (mkdir-before-append), :205 (per-line flush).\n */\nexport function appendJsonl(path: string, record: unknown): void {\n mkdirSync(dirname(path), { recursive: true });\n const prefix = needsLineBreakBefore(path) ? \"\\n\" : \"\";\n // M93 (adversarial review, H1) — `0o600`. `appendFileSync` takes no `mode`, so the permission came\n // from the umask: under `umask 022` the transcript was born `0664`, world-readable. The previous\n // path (`replaceFileAtomic`) pinned `0o600` on purpose — \"holds the FULL in-flight content\n // (credential snapshots, OAuth tokens)\" (`atomic-write.ts:107`) — and switching to append lost\n // that silently. The same class had already been caught in the consumer (`atomic-sync.ts`, M88\n // HIGH-1).\n //\n // `mode` only applies on CREATION; a pre-existing file keeps whatever permission it already has.\n const fd = openSync(path, \"a\", 0o600);\n try {\n writeSync(fd, `${prefix}${JSON.stringify(record)}\\n`);\n } finally {\n closeSync(fd);\n }\n}\n\n/**\n * Does the file end without a `\\n`? Then the last line is truncated — a crash mid-append.\n *\n * Without this check the next append **glues** itself onto the middle of the broken line, producing\n * an invalid line the reader discards: the NEW record disappears along with the partial one. The\n * previous path (read-modify-write) self-healed from this because it rewrote the whole file.\n * Measured in M93's adversarial review (H2): after an append over a truncated file, the\n * just-written record was no longer readable.\n *\n * Reads **one byte**, not the file.\n */\nfunction needsLineBreakBefore(path: string): boolean {\n let fd: number;\n try {\n fd = openSync(path, \"r\");\n } catch {\n return false; // the file does not exist yet: nothing to splice onto\n }\n try {\n const size = fstatSync(fd).size;\n if (size === 0) return false;\n const buf = Buffer.alloc(1);\n readSync(fd, buf, 0, 1, size - 1);\n return buf[0] !== 0x0a;\n } finally {\n closeSync(fd);\n }\n}\n\n/**\n * Read the set of keys from an existing JSONL file for which `keyFn(parsed)`\n * returns a non-empty string. Used to resume a crashed batch by skipping rows\n * already persisted with a successful result. A trailing partial line from an\n * interrupted append is tolerated (skipped, not thrown), and a missing file\n * yields an empty set.\n *\n * referencia: swebench-batch.ts:113 (readDoneIds), :129 (success-only),\n * :131 (tolerate partial line).\n */\nexport function readJsonlIds(\n path: string,\n keyFn: (parsed: Record<string, unknown>) => string | undefined,\n): Set<string> {\n const done = new Set<string>();\n let text: string;\n try {\n text = readFileSync(path, \"utf8\");\n } catch {\n return done; // no file yet → nothing done\n }\n for (const rawLine of text.split(\"\\n\")) {\n // A trailing partial line from an interrupted run parses to undefined → skipped.\n const parsed = tryParseObjectLine(rawLine.trim());\n if (parsed === undefined) continue;\n const key = keyFn(parsed);\n if (typeof key === \"string\" && key.length > 0) done.add(key);\n }\n return done;\n}\n"]}
1
+ {"version":3,"sources":["../src/internal/persistence/file-lock.ts","../src/internal/persistence/jsonl.ts"],"names":["diag","withCwdMutex","readFileSync","path","mkdirSync","dirname","openSync","writeSync","closeSync","fstatSync","readSync"],"mappings":";;;;;;;;AAiCA,IAAI,MAAA;AACJ,IAAI,aAAA,GAAgB,KAAA;AACpB,IAAI,gBAAA,GAAmB,KAAA;AAEvB,eAAe,iBAAA,GAA0D;AACvE,EAAA,IAAI,MAAA,KAAW,QAAW,OAAO,MAAA;AACjC,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,OAAO,iBAAiB,CAAA;AAM1C,IAAA,IAAI,CAAC,kBAAA,CAAmB,GAAG,CAAA,EAAG;AAC5B,MAAA,IAAI,CAAC,gBAAA,EAAkB;AACrB,QAAA,gBAAA,GAAmB,IAAA;AACnB,QAAAA,sBAAA;AAAA,UACE;AAAA,SAKF;AAAA,MACF;AACA,MAAA,MAAA,GAAS,IAAA;AACT,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,MAAA,GAAS,GAAA;AAAA,EACX,CAAA,CAAA,MAAQ;AACN,IAAA,MAAA,GAAS,IAAA;AAAA,EACX;AACA,EAAA,OAAO,MAAA;AACT;AAaA,SAAS,mBAAmB,GAAA,EAAuB;AACjD,EAAA,IAAI,QAAQ,IAAA,IAAQ,GAAA,KAAQ,UAAa,OAAO,GAAA,KAAQ,UAAU,OAAO,KAAA;AACzE,EAAA,MAAM,CAAA,GAAI,GAAA;AACV,EAAA,OAAO,OAAO,CAAA,CAAE,IAAA,KAAS,UAAA,IAAc,OAAO,EAAE,MAAA,KAAW,UAAA;AAC7D;AAmDA,eAAsB,YAAA,CACpB,IAAA,EACA,EAAA,EACA,OAAA,EACY;AACZ,EAAA,MAAM,GAAA,GAAM,MAAM,iBAAA,EAAkB;AAEpC,EAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,IAAA,IAAI,CAAC,aAAA,EAAe;AAClB,MAAA,aAAA,GAAgB,IAAA;AAChB,MAAAA,sBAAA;AAAA,QACE;AAAA,OAGF;AAAA,IACF;AACA,IAAA,OAAOC,8BAAA,CAAa,CAAA,UAAA,EAAa,IAAI,CAAA,CAAA,EAAI,EAAE,CAAA;AAAA,EAC7C;AAOA,EAAA,OAAOA,8BAAA,CAAa,CAAA,UAAA,EAAa,IAAI,CAAA,CAAA,EAAI,YAAY;AACnD,IAAA,MAAM,OAAA,GAAU,MAAM,GAAA,CAAI,IAAA,CAAK,IAAA,EAAM;AAAA;AAAA,MAEnC,YAAA,EAAc,GAAG,IAAI,CAAA,KAAA,CAAA;AAAA,MACrB,QAAA,EAAU,KAAA;AAAA,MACV,KAAA,EAAO,SAAS,KAAA,IAAS,GAAA;AAAA,MACzB,OAAA,EAAS;AAAA,QACP,OAAA,EAAS,SAAS,OAAA,IAAW,CAAA;AAAA,QAC7B,MAAA,EAAQ,SAAS,WAAA,IAAe,GAAA;AAAA,QAChC,UAAA,EAAY,GAAA;AAAA,QACZ,UAAA,EAAY;AAAA;AACd,KACD,CAAA;AAED,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,EAAA,EAAG;AAAA,IAClB,CAAA,SAAE;AACA,MAAA,MAAM,OAAA,EAAQ;AAAA,IAChB;AAAA,EACF,CAAC,CAAA;AACH;ACrJO,IAAM,eAAA,GAAN,cAA8B,KAAA,CAAM;AAAA,EACzC,WAAA,CACE,SACS,IAAA,EACT;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAFJ,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAGT,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AAAA,EAJW,IAAA;AAKb;AAEA,SAAS,cAAc,KAAA,EAAkD;AACvE,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;AAGA,SAAS,mBAAmB,IAAA,EAAmD;AAC7E,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AAC9B,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,EAC1B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,aAAA,CAAc,MAAM,CAAA,GAAI,MAAA,GAAS,MAAA;AAC1C;AAQO,SAAS,SAAA,CACd,IAAA,EACA,IAAA,GASI,EAAC,EACA;AACL,EAAA,MAAM,QAAQC,eAAA,CAAa,IAAA,EAAM,MAAM,CAAA,CAAE,MAAM,IAAI,CAAA;AACnD,EAAA,MAAM,MAAW,EAAC;AAClB,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,MAAA,EAAQ,KAAK,CAAA,EAAG;AACxC,IAAA,MAAM,aAAa,CAAA,GAAI,CAAA;AACvB,IAAA,MAAM,IAAA,GAAA,CAAQ,KAAA,CAAM,CAAC,CAAA,IAAK,IAAI,IAAA,EAAK;AACnC,IAAA,IAAI,IAAA,CAAK,WAAW,CAAA,EAAG;AAGvB,IAAA,MAAM,MAAA,GAAS,SAAA;AAAA,MACb,IAAA;AAAA,MACA,UAAA;AAAA,MACA,IAAA,CAAK,2BAAA,KAAgC,IAAA,IAAQ,UAAA,KAAe,KAAA,CAAM;AAAA,KACpE;AACA,IAAA,IAAI,WAAW,MAAA,EAAW;AAC1B,IAAA,GAAA,CAAI,IAAA,CAAK,KAAK,GAAA,GAAM,IAAA,CAAK,IAAI,MAAA,EAAQ,UAAU,IAAK,MAAuB,CAAA;AAAA,EAC7E;AACA,EAAA,OAAO,GAAA;AACT;AASA,SAAS,SAAA,CACP,IAAA,EACA,UAAA,EACA,QAAA,EACqC;AACrC,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,EAC1B,CAAA,CAAA,MAAQ;AACN,IAAA,IAAI,UAAU,OAAO,MAAA;AACrB,IAAA,MAAM,IAAI,eAAA,CAAgB,CAAA,KAAA,EAAQ,UAAU,kBAAkB,UAAU,CAAA;AAAA,EAC1E;AACA,EAAA,IAAI,CAAC,aAAA,CAAc,MAAM,CAAA,EAAG;AAC1B,IAAA,MAAM,IAAI,eAAA,CAAgB,CAAA,KAAA,EAAQ,UAAU,uBAAuB,UAAU,CAAA;AAAA,EAC/E;AACA,EAAA,OAAO,MAAA;AACT;AAUO,SAAS,WAAA,CAAYC,QAAc,MAAA,EAAuB;AAC/D,EAAAC,YAAA,CAAUC,aAAQF,MAAI,CAAA,EAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AAC5C,EAAA,MAAM,MAAA,GAAS,oBAAA,CAAqBA,MAAI,CAAA,GAAI,IAAA,GAAO,EAAA;AASnD,EAAA,MAAM,EAAA,GAAKG,WAAA,CAASH,MAAA,EAAM,GAAA,EAAK,GAAK,CAAA;AACpC,EAAA,IAAI;AACF,IAAAI,YAAA,CAAU,IAAI,CAAA,EAAG,MAAM,GAAG,IAAA,CAAK,SAAA,CAAU,MAAM,CAAC;AAAA,CAAI,CAAA;AAAA,EACtD,CAAA,SAAE;AACA,IAAAC,YAAA,CAAU,EAAE,CAAA;AAAA,EACd;AACF;AAaA,SAAS,qBAAqB,IAAA,EAAuB;AACnD,EAAA,IAAI,EAAA;AACJ,EAAA,IAAI;AACF,IAAA,EAAA,GAAKF,WAAA,CAAS,MAAM,GAAG,CAAA;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAOG,YAAA,CAAU,EAAE,CAAA,CAAE,IAAA;AAC3B,IAAA,IAAI,IAAA,KAAS,GAAG,OAAO,KAAA;AACvB,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,KAAA,CAAM,CAAC,CAAA;AAC1B,IAAAC,WAAA,CAAS,EAAA,EAAI,GAAA,EAAK,CAAA,EAAG,CAAA,EAAG,OAAO,CAAC,CAAA;AAChC,IAAA,OAAO,GAAA,CAAI,CAAC,CAAA,KAAM,EAAA;AAAA,EACpB,CAAA,SAAE;AACA,IAAAF,YAAA,CAAU,EAAE,CAAA;AAAA,EACd;AACF;AAYO,SAAS,YAAA,CACd,MACA,KAAA,EACa;AACb,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI;AACF,IAAA,IAAA,GAAON,eAAA,CAAa,MAAM,MAAM,CAAA;AAAA,EAClC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,KAAA,MAAW,OAAA,IAAW,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAG;AAEtC,IAAA,MAAM,MAAA,GAAS,kBAAA,CAAmB,OAAA,CAAQ,IAAA,EAAM,CAAA;AAChD,IAAA,IAAI,WAAW,MAAA,EAAW;AAC1B,IAAA,MAAM,GAAA,GAAM,MAAM,MAAM,CAAA;AACxB,IAAA,IAAI,OAAO,QAAQ,QAAA,IAAY,GAAA,CAAI,SAAS,CAAA,EAAG,IAAA,CAAK,IAAI,GAAG,CAAA;AAAA,EAC7D;AACA,EAAA,OAAO,IAAA;AACT","file":"chunk-DMTZ3FII.cjs","sourcesContent":["/**\n * Cross-process file lock helper (ADR D61).\n *\n * Uses `proper-lockfile` (optional peer dep) for cross-process locks. When\n * the peer dep is absent, falls back to `withCwdMutex` (in-process only)\n * with a one-shot stderr warning.\n *\n * EC-1 fix: uses a companion `<path>.lock` file with `realpath: false` so\n * `withFileLock` works even when the target `path` does not exist yet.\n * Without this, fresh installs that lock-then-create would crash with ENOENT.\n *\n * @internal\n */\n\nimport { diag } from \"../diagnostics.js\";\nimport { withCwdMutex } from \"./cwd-mutex.js\";\n\ninterface ProperLockfileModule {\n lock: (file: string, options: ProperLockfileOptions) => Promise<() => Promise<void>>;\n}\n\ninterface ProperLockfileOptions {\n lockfilePath?: string;\n realpath?: boolean;\n stale?: number;\n retries?: {\n retries: number;\n factor?: number;\n minTimeout?: number;\n maxTimeout?: number;\n };\n}\n\nlet cached: ProperLockfileModule | null | undefined;\nlet warnedMissing = false;\nlet warnedStructural = false;\n\nasync function getProperLockfile(): Promise<ProperLockfileModule | null> {\n if (cached !== undefined) return cached;\n try {\n const mod = await import(\"proper-lockfile\");\n // T5.9 — supply-chain hardening: validate the imported module\n // exposes the API surface we depend on BEFORE caching it. A\n // tampered or incompatible version that lacks `lock`/`unlock`\n // functions gets treated as \"not installed\" with an advisory\n // warning — never silently used.\n if (!validateLockModule(mod)) {\n if (!warnedStructural) {\n warnedStructural = true;\n diag(\n \"[theokit-sdk] proper-lockfile: imported module does NOT expose \" +\n \"the expected `lock`/`unlock` API surface. This may indicate a \" +\n \"supply-chain compromise or an incompatible major version. \" +\n \"Falling back to in-process mutex (no cross-process safety). \" +\n \"Reinstall with: pnpm add proper-lockfile@^11\\n\",\n );\n }\n cached = null;\n return cached;\n }\n cached = mod as ProperLockfileModule;\n } catch {\n cached = null;\n }\n return cached;\n}\n\n/**\n * T5.9 — Structural validation of the dynamically-imported\n * `proper-lockfile` module. Verifies the API surface we depend on\n * (`lock` and `unlock` as functions) is present. Pure function —\n * never throws, never mutates, never performs I/O.\n *\n * Exported via `__TESTING__validateLockModule` seam so unit tests\n * can drive the check without spinning up the dynamic import.\n *\n * @internal\n */\nfunction validateLockModule(mod: unknown): boolean {\n if (mod === null || mod === undefined || typeof mod !== \"object\") return false;\n const m = mod as Record<string, unknown>;\n return typeof m.lock === \"function\" && typeof m.unlock === \"function\";\n}\n\n/**\n * T5.9 — Test seam: expose the structural validator for unit tests.\n * NOT included in the public barrel.\n *\n * @internal\n */\nexport function __TESTING__validateLockModule(mod: unknown): boolean {\n return validateLockModule(mod);\n}\n\n/**\n * T5.9 — Test seam: reset the module cache + warning flags between\n * tests so each test starts fresh. NOT included in the public barrel.\n *\n * @internal\n */\nexport function __TESTING__resetFileLockCache(): void {\n cached = undefined;\n warnedMissing = false;\n warnedStructural = false;\n}\n\n/**\n * Options for `withFileLock`.\n *\n * @internal\n */\nexport interface FileLockOptions {\n /** Stale lock timeout in ms. Default 30_000 (30s). */\n stale?: number;\n /** Max retries on busy lock. Default 5. */\n retries?: number;\n /** Backoff factor between retries. Default 1.5. */\n retryFactor?: number;\n}\n\n/**\n * Run `fn` while holding an OS-level cross-process lock on `path`.\n *\n * If `proper-lockfile` is installed, uses it with a companion `<path>.lock`\n * file (`realpath: false`, so target file does NOT need to exist yet).\n * Otherwise falls back to in-process `withCwdMutex` and prints a one-shot\n * stderr warning telling the user to install `proper-lockfile` for\n * cross-process safety.\n *\n * The lock is released even when `fn` throws.\n *\n * @internal\n */\nexport async function withFileLock<T>(\n path: string,\n fn: () => Promise<T>,\n options?: FileLockOptions,\n): Promise<T> {\n const lib = await getProperLockfile();\n\n if (lib === null) {\n if (!warnedMissing) {\n warnedMissing = true;\n diag(\n \"[theokit-sdk] proper-lockfile not installed; \" +\n \"cross-process file lock unavailable. \" +\n \"Install with: pnpm add proper-lockfile\\n\",\n );\n }\n return withCwdMutex(`file-lock:${path}`, fn);\n }\n\n // proper-lockfile errors immediately on same-process concurrent acquire\n // (\"Lock file is already being held\"). Wrap with cwd-mutex first so\n // in-process callers queue and only ONE thread at a time enters the\n // cross-process acquire path. Combined: full in-process + cross-process\n // serialization.\n return withCwdMutex(`file-lock:${path}`, async () => {\n const release = await lib.lock(path, {\n // EC-1: companion lockfile, target path may not exist yet.\n lockfilePath: `${path}.lock`,\n realpath: false,\n stale: options?.stale ?? 30_000,\n retries: {\n retries: options?.retries ?? 5,\n factor: options?.retryFactor ?? 1.5,\n minTimeout: 100,\n maxTimeout: 5_000,\n },\n });\n\n try {\n return await fn();\n } finally {\n await release();\n }\n });\n}\n\n/**\n * Test helper — resets the cached proper-lockfile module + warning flag.\n * Allows tests to simulate \"module absent\" by clearing cache then\n * monkey-patching the dynamic import resolution.\n *\n * @internal\n */\nexport function _resetFileLockCacheForTesting(): void {\n cached = undefined;\n warnedMissing = false;\n}\n","/**\n * Durable JSONL primitives shared by the eval harness (M6).\n *\n * - `loadJsonl` — generic dataset reader (split/trim/skip-blank/parse) with a\n * line-numbered {@link JsonlParseError}. The dataset SCHEMA is the caller's\n * concern via `map` (M6 ADR D3) — this module owns only the parse.\n * - `appendJsonl` / `readJsonlIds` — crash-durable, resumable batch persistence\n * (M6 ADR D1): each record is appended as one whole `\\n`-terminated line the\n * instant it is produced, and a re-run resumes by skipping already-keyed rows.\n *\n * referencia: knowledge-base/references/theocode-eval/lib/swebench-dataset.ts:82\n * (parseJsonl + line-N error) and swebench-batch.ts:113,205 (resume + per-line\n * flush).\n *\n * @internal\n */\nimport {\n closeSync,\n fstatSync,\n mkdirSync,\n openSync,\n readFileSync,\n readSync,\n writeSync,\n} from \"node:fs\";\nimport { dirname } from \"node:path\";\n\n/** Raised when a JSONL line is not valid JSON or is not a JSON object. Carries the 1-based line number. */\nexport class JsonlParseError extends Error {\n constructor(\n message: string,\n readonly line: number,\n ) {\n super(message);\n this.name = \"JsonlParseError\";\n }\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Parse a single trimmed line to a plain object, or `undefined` if blank / invalid / non-object. */\nfunction tryParseObjectLine(line: string): Record<string, unknown> | undefined {\n if (line.length === 0) return undefined;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n return undefined;\n }\n return isPlainObject(parsed) ? parsed : undefined;\n}\n\n/**\n * Parse a JSONL file into rows. Blank lines are skipped. A malformed or\n * non-object line throws {@link JsonlParseError} naming the 1-based line. When\n * `map` is provided, each raw object is mapped to the typed row (the SWE-bench\n * schema lives in the caller's `map`, per M6 ADR D3).\n */\nexport function loadJsonl<T = Record<string, unknown>>(\n path: string,\n opts: {\n map?: (raw: Record<string, unknown>, lineNumber: number) => T;\n /**\n * M81 — tolerate a truncated LAST line (a crash artifact: the process died mid-write).\n *\n * Opt-in on purpose. As a default it would also swallow corruption in the MIDDLE of the file,\n * turning loud data loss into silent data loss — the wrong trade for a session store.\n */\n tolerateTrailingPartialLine?: boolean;\n } = {},\n): T[] {\n const lines = readFileSync(path, \"utf8\").split(\"\\n\");\n const out: T[] = [];\n for (let i = 0; i < lines.length; i += 1) {\n const lineNumber = i + 1;\n const line = (lines[i] ?? \"\").trim();\n if (line.length === 0) continue;\n // M81 — `undefined` = a tolerated invalid line (the last one, truncated by a crash). Any other\n // invalid line has already thrown inside `parseLine`.\n const parsed = parseLine(\n line,\n lineNumber,\n opts.tolerateTrailingPartialLine === true && lineNumber === lines.length,\n );\n if (parsed === undefined) break;\n out.push(opts.map ? opts.map(parsed, lineNumber) : (parsed as unknown as T));\n }\n return out;\n}\n\n/**\n * Parses ONE line, returning `undefined` when it is a tolerated truncated last line.\n *\n * Extracted because `loadJsonl` went over the cognitive-complexity ceiling once it gained the\n * tolerance — and because parsing a line and iterating a file are two responsibilities that were\n * only together out of habit.\n */\nfunction parseLine(\n line: string,\n lineNumber: number,\n tolerate: boolean,\n): Record<string, unknown> | undefined {\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n if (tolerate) return undefined;\n throw new JsonlParseError(`line ${lineNumber}: invalid JSON`, lineNumber);\n }\n if (!isPlainObject(parsed)) {\n throw new JsonlParseError(`line ${lineNumber}: not a JSON object`, lineNumber);\n }\n return parsed;\n}\n\n/**\n * Append one record as a whole `\\n`-terminated JSON line. Creates the parent dir\n * if missing. `appendFileSync` is synchronous, so within a single Node process\n * the event loop serializes writes and each call writes its line atomically —\n * interleave-safe for the bounded-concurrency batch runner.\n *\n * referencia: swebench-batch.ts:192 (mkdir-before-append), :205 (per-line flush).\n */\nexport function appendJsonl(path: string, record: unknown): void {\n mkdirSync(dirname(path), { recursive: true });\n const prefix = needsLineBreakBefore(path) ? \"\\n\" : \"\";\n // M93 (adversarial review, H1) — `0o600`. `appendFileSync` takes no `mode`, so the permission came\n // from the umask: under `umask 022` the transcript was born `0664`, world-readable. The previous\n // path (`replaceFileAtomic`) pinned `0o600` on purpose — \"holds the FULL in-flight content\n // (credential snapshots, OAuth tokens)\" (`atomic-write.ts:107`) — and switching to append lost\n // that silently. The same class had already been caught in the consumer (`atomic-sync.ts`, M88\n // HIGH-1).\n //\n // `mode` only applies on CREATION; a pre-existing file keeps whatever permission it already has.\n const fd = openSync(path, \"a\", 0o600);\n try {\n writeSync(fd, `${prefix}${JSON.stringify(record)}\\n`);\n } finally {\n closeSync(fd);\n }\n}\n\n/**\n * Does the file end without a `\\n`? Then the last line is truncated — a crash mid-append.\n *\n * Without this check the next append **glues** itself onto the middle of the broken line, producing\n * an invalid line the reader discards: the NEW record disappears along with the partial one. The\n * previous path (read-modify-write) self-healed from this because it rewrote the whole file.\n * Measured in M93's adversarial review (H2): after an append over a truncated file, the\n * just-written record was no longer readable.\n *\n * Reads **one byte**, not the file.\n */\nfunction needsLineBreakBefore(path: string): boolean {\n let fd: number;\n try {\n fd = openSync(path, \"r\");\n } catch {\n return false; // the file does not exist yet: nothing to splice onto\n }\n try {\n const size = fstatSync(fd).size;\n if (size === 0) return false;\n const buf = Buffer.alloc(1);\n readSync(fd, buf, 0, 1, size - 1);\n return buf[0] !== 0x0a;\n } finally {\n closeSync(fd);\n }\n}\n\n/**\n * Read the set of keys from an existing JSONL file for which `keyFn(parsed)`\n * returns a non-empty string. Used to resume a crashed batch by skipping rows\n * already persisted with a successful result. A trailing partial line from an\n * interrupted append is tolerated (skipped, not thrown), and a missing file\n * yields an empty set.\n *\n * referencia: swebench-batch.ts:113 (readDoneIds), :129 (success-only),\n * :131 (tolerate partial line).\n */\nexport function readJsonlIds(\n path: string,\n keyFn: (parsed: Record<string, unknown>) => string | undefined,\n): Set<string> {\n const done = new Set<string>();\n let text: string;\n try {\n text = readFileSync(path, \"utf8\");\n } catch {\n return done; // no file yet → nothing done\n }\n for (const rawLine of text.split(\"\\n\")) {\n // A trailing partial line from an interrupted run parses to undefined → skipped.\n const parsed = tryParseObjectLine(rawLine.trim());\n if (parsed === undefined) continue;\n const key = keyFn(parsed);\n if (typeof key === \"string\" && key.length > 0) done.add(key);\n }\n return done;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { setupStructuredOutput, makeOutputTool, buildTransientAgentOptions, buildToolPrompt, extractUsage, disposeAndDeleteTransient } from './chunk-EUB7YLU2.js';
1
+ import { setupStructuredOutput, makeOutputTool, buildTransientAgentOptions, buildToolPrompt, extractUsage, disposeAndDeleteTransient } from './chunk-JZUPMTJY.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-6XZBKFQ7.js.map
145
- //# sourceMappingURL=chunk-6XZBKFQ7.js.map
144
+ //# sourceMappingURL=chunk-DU7DE543.js.map
145
+ //# sourceMappingURL=chunk-DU7DE543.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/stream-object.ts"],"names":[],"mappings":";;;AA+EO,IAAM,iBAAA,GAAN,cAAgC,KAAA,CAAM;AAAA,EACzB,IAAA,GAAO,mBAAA;AAAA,EAChB,IAAA;AAAA,EACS,KAAA;AAAA,EAClB,WAAA,CAAY,IAAA,EAAuC,OAAA,EAAiB,KAAA,EAAiB;AACnF,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAI,KAAA,KAAU,MAAA,EAAW,IAAA,CAAK,KAAA,GAAQ,KAAA;AAAA,EACxC;AACF;AAgBA,gBAAuB,gBAAA,CACrB,SACA,IAAA,EACsE;AACtE,EAAA,MAAM,EAAE,UAAA,EAAY,UAAA,EAAY,YAAA,EAAa,GAAI,qBAAA;AAAA,IAC/C,OAAA,CAAQ,MAAA;AAAA,IACR,OAAA,CAAQ;AAAA,GACV;AACA,EAAA,IAAI,WAAA;AACJ,EAAA,IAAI,SAAA,GAAY,YAAA;AAEhB,EAAA,MAAM,UAAA,GAAa,cAAA,CAAe,UAAA,EAAY,CAAC,KAAA,KAAU;AAEvD,IAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,MAAA,WAAA,GAAc,KAAA;AAAA,IAChB;AACA,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,EAAE,EAAA,EAAI,MAAM,CAAA;AAAA,EACpC,CAAC,CAAA;AAED,EAAA,MAAM,eAA6B,0BAAA,CAA2B;AAAA,IAC5D,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,UAAA;AAAA,IACA,GAAI,QAAQ,YAAA,KAAiB,MAAA,GAAY,EAAE,YAAA,EAAc,OAAA,CAAQ,YAAA,EAAa,GAAI,EAAC;AAAA,IACnF,GAAI,QAAQ,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,OAAA,CAAQ,MAAA,EAAO,GAAI,EAAC;AAAA,IACjE,GAAI,QAAQ,SAAA,KAAc,MAAA,GAAY,EAAE,SAAA,EAAW,OAAA,CAAQ,SAAA,EAAU,GAAI;AAAC,GAC3E,CAAA;AACD,EAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,MAAA,CAAO,YAAY,CAAA;AAC5C,EAAA,MAAM,WAAA,GAAc,eAAA,CAAgB,OAAA,CAAQ,MAAM,CAAA;AAElD,EAAA,IAAI;AACF,IAAA,IAAI,cAAA;AACJ,IAAA,IAAI,cAAA,GAAiB,CAAA;AAErB,IAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,UAAA,EAAY,WAAW,CAAA,EAAG;AACzD,MAAA,WAAA,GAAc,KAAA,CAAA;AACd,MAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,IAAA,CAAK,WAAW,CAAA;AAGxC,MAAA,IAAI,UAAA,GAAa,EAAA;AACjB,MAAA,WAAA,MAAiB,GAAA,IAAO,GAAA,CAAI,MAAA,EAAO,EAAG;AACpC,QAAA,IAAI,GAAA,CAAI,SAAS,WAAA,EAAa;AAC5B,UAAA,MAAM,UAAU,GAAA,CAAI,OAAA,CAAQ,QACzB,MAAA,CAAO,CAAC,MAA2C,CAAA,CAAE,IAAA,KAAS,MAAM,CAAA,CACpE,IAAI,CAAC,CAAA,KAAM,EAAE,IAAI,CAAA,CACjB,KAAK,EAAE,CAAA;AACV,UAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACtB,YAAA,UAAA,IAAc,OAAA;AACd,YAAA,MAAM,OAAA,GAAU,sBAAA,CAAuB,UAAA,EAAY,OAAA,CAAQ,MAAM,CAAA;AACjE,YAAA,IAAI,YAAY,KAAA,CAAA,EAAW;AACzB,cAAA,cAAA,IAAkB,CAAA;AAClB,cAAA,MAAM;AAAA,gBACJ,IAAA,EAAM,SAAA;AAAA,gBACN,OAAA;AAAA,gBACA,OAAA,EAAS;AAAA,eACX;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,MAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,IAAA,EAAK;AAC9B,MAAA,SAAA,GAAY,aAAa,MAAM,CAAA;AAE/B,MAAA,IAAI,gBAAgB,KAAA,CAAA,EAAW;AAI7B,QAAA,IAAI,MAAA,CAAO,MAAA,KAAW,OAAA,IAAW,MAAA,CAAO,UAAU,KAAA,CAAA,EAAW;AAC3D,UAAA,MAAM,IAAI,iBAAA;AAAA,YACR,cAAA;AAAA,YACA,CAAA,+CAAA,EAAkD,OAAO,KAAA,CAAM,OAAA,IAAW,eAAe,CAAA,EAAA,EAAK,MAAA,CAAO,KAAA,CAAM,IAAA,IAAQ,GAAG,CAAA,CAAA,CAAA;AAAA,YACtH,MAAA,CAAO;AAAA,WACT;AAAA,QACF;AACA,QAAA,IAAI,YAAY,UAAA,EAAY;AAC1B,UAAA,MAAM,IAAI,iBAAA;AAAA,YACR,cAAA;AAAA,YACA;AAAA,WACF;AAAA,QACF;AACA,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,CAAO,SAAA,CAAU,WAAW,CAAA;AACnD,MAAA,IAAI,OAAO,OAAA,EAAS;AAClB,QAAA,MAAM;AAAA,UACJ,IAAA,EAAM,UAAA;AAAA,UACN,QAAQ,MAAA,CAAO,IAAA;AAAA,UACf,GAAA,EAAK,WAAA;AAAA,UACL,KAAA,EAAO,SAAA;AAAA,UACP,YAAA,EAAc;AAAA,SAChB;AACA,QAAA;AAAA,MACF;AACA,MAAA,cAAA,GAAiB,MAAA,CAAO,KAAA;AAAA,IAC1B;AAEA,IAAA,MAAM,IAAI,iBAAA;AAAA,MACR,cAAA;AAAA,MACA,wCAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF,CAAA,SAAE;AAGA,IAAA,MAAM,yBAAA,CAA0B,KAAA,EAAO,IAAA,CAAK,MAAM,CAAA;AAAA,EACpD;AACF;AAcA,SAAS,sBAAA,CAA0C,MAAc,MAAA,EAAgC;AAC/F,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AAC9B,EAAA,IAAI,KAAA,GAAQ,GAAG,OAAO,MAAA;AAEtB,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,IAAI,QAAA,GAAW,KAAA;AACf,EAAA,IAAI,SAAA,GAAY,KAAA;AAChB,EAAA,IAAI,GAAA,GAAM,EAAA;AACV,EAAA,KAAA,IAAS,IAAI,KAAA,EAAO,CAAA,GAAI,IAAA,CAAK,MAAA,EAAQ,KAAK,CAAA,EAAG;AAC3C,IAAA,MAAM,EAAA,GAAK,KAAK,CAAC,CAAA;AACjB,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,SAAA,GAAY,KAAA;AACZ,MAAA;AAAA,IACF;AACA,IAAA,IAAI,EAAA,KAAO,QAAQ,QAAA,EAAU;AAC3B,MAAA,SAAA,GAAY,IAAA;AACZ,MAAA;AAAA,IACF;AACA,IAAA,IAAI,OAAO,GAAA,EAAK;AACd,MAAA,QAAA,GAAW,CAAC,QAAA;AACZ,MAAA;AAAA,IACF;AACA,IAAA,IAAI,QAAA,EAAU;AACd,IAAA,IAAI,EAAA,KAAO,KAAK,KAAA,IAAS,CAAA;AAAA,SAAA,IAChB,OAAO,GAAA,EAAK;AACnB,MAAA,KAAA,IAAS,CAAA;AACT,MAAA,IAAI,KAAA,KAAU,GAAG,GAAA,GAAM,CAAA;AAAA,IACzB;AAAA,EACF;AACA,EAAA,IAAI,GAAA,GAAM,GAAG,OAAO,MAAA;AACpB,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,KAAA,EAAO,MAAM,CAAC,CAAA;AAC3C,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,SAAS,CAAA;AAAA,EAC/B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AAGA,EAAA,MAAM,eAAgB,MAAA,CAAkD,OAAA;AACxE,EAAA,MAAM,cAAc,OAAO,YAAA,KAAiB,aAAa,YAAA,CAAa,IAAA,CAAK,MAAM,CAAA,GAAI,MAAA;AACrF,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,SAAA,CAAU,MAAM,CAAA;AAC3C,EAAA,OAAO,MAAA,CAAO,OAAA,GAAU,MAAA,CAAO,IAAA,GAAO,MAAA;AACxC","file":"chunk-6XZBKFQ7.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":";;;AA+EO,IAAM,iBAAA,GAAN,cAAgC,KAAA,CAAM;AAAA,EACzB,IAAA,GAAO,mBAAA;AAAA,EAChB,IAAA;AAAA,EACS,KAAA;AAAA,EAClB,WAAA,CAAY,IAAA,EAAuC,OAAA,EAAiB,KAAA,EAAiB;AACnF,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAI,KAAA,KAAU,MAAA,EAAW,IAAA,CAAK,KAAA,GAAQ,KAAA;AAAA,EACxC;AACF;AAgBA,gBAAuB,gBAAA,CACrB,SACA,IAAA,EACsE;AACtE,EAAA,MAAM,EAAE,UAAA,EAAY,UAAA,EAAY,YAAA,EAAa,GAAI,qBAAA;AAAA,IAC/C,OAAA,CAAQ,MAAA;AAAA,IACR,OAAA,CAAQ;AAAA,GACV;AACA,EAAA,IAAI,WAAA;AACJ,EAAA,IAAI,SAAA,GAAY,YAAA;AAEhB,EAAA,MAAM,UAAA,GAAa,cAAA,CAAe,UAAA,EAAY,CAAC,KAAA,KAAU;AAEvD,IAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,MAAA,WAAA,GAAc,KAAA;AAAA,IAChB;AACA,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,EAAE,EAAA,EAAI,MAAM,CAAA;AAAA,EACpC,CAAC,CAAA;AAED,EAAA,MAAM,eAA6B,0BAAA,CAA2B;AAAA,IAC5D,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,UAAA;AAAA,IACA,GAAI,QAAQ,YAAA,KAAiB,MAAA,GAAY,EAAE,YAAA,EAAc,OAAA,CAAQ,YAAA,EAAa,GAAI,EAAC;AAAA,IACnF,GAAI,QAAQ,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,OAAA,CAAQ,MAAA,EAAO,GAAI,EAAC;AAAA,IACjE,GAAI,QAAQ,SAAA,KAAc,MAAA,GAAY,EAAE,SAAA,EAAW,OAAA,CAAQ,SAAA,EAAU,GAAI;AAAC,GAC3E,CAAA;AACD,EAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,MAAA,CAAO,YAAY,CAAA;AAC5C,EAAA,MAAM,WAAA,GAAc,eAAA,CAAgB,OAAA,CAAQ,MAAM,CAAA;AAElD,EAAA,IAAI;AACF,IAAA,IAAI,cAAA;AACJ,IAAA,IAAI,cAAA,GAAiB,CAAA;AAErB,IAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,UAAA,EAAY,WAAW,CAAA,EAAG;AACzD,MAAA,WAAA,GAAc,KAAA,CAAA;AACd,MAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,IAAA,CAAK,WAAW,CAAA;AAGxC,MAAA,IAAI,UAAA,GAAa,EAAA;AACjB,MAAA,WAAA,MAAiB,GAAA,IAAO,GAAA,CAAI,MAAA,EAAO,EAAG;AACpC,QAAA,IAAI,GAAA,CAAI,SAAS,WAAA,EAAa;AAC5B,UAAA,MAAM,UAAU,GAAA,CAAI,OAAA,CAAQ,QACzB,MAAA,CAAO,CAAC,MAA2C,CAAA,CAAE,IAAA,KAAS,MAAM,CAAA,CACpE,IAAI,CAAC,CAAA,KAAM,EAAE,IAAI,CAAA,CACjB,KAAK,EAAE,CAAA;AACV,UAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACtB,YAAA,UAAA,IAAc,OAAA;AACd,YAAA,MAAM,OAAA,GAAU,sBAAA,CAAuB,UAAA,EAAY,OAAA,CAAQ,MAAM,CAAA;AACjE,YAAA,IAAI,YAAY,KAAA,CAAA,EAAW;AACzB,cAAA,cAAA,IAAkB,CAAA;AAClB,cAAA,MAAM;AAAA,gBACJ,IAAA,EAAM,SAAA;AAAA,gBACN,OAAA;AAAA,gBACA,OAAA,EAAS;AAAA,eACX;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,MAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,IAAA,EAAK;AAC9B,MAAA,SAAA,GAAY,aAAa,MAAM,CAAA;AAE/B,MAAA,IAAI,gBAAgB,KAAA,CAAA,EAAW;AAI7B,QAAA,IAAI,MAAA,CAAO,MAAA,KAAW,OAAA,IAAW,MAAA,CAAO,UAAU,KAAA,CAAA,EAAW;AAC3D,UAAA,MAAM,IAAI,iBAAA;AAAA,YACR,cAAA;AAAA,YACA,CAAA,+CAAA,EAAkD,OAAO,KAAA,CAAM,OAAA,IAAW,eAAe,CAAA,EAAA,EAAK,MAAA,CAAO,KAAA,CAAM,IAAA,IAAQ,GAAG,CAAA,CAAA,CAAA;AAAA,YACtH,MAAA,CAAO;AAAA,WACT;AAAA,QACF;AACA,QAAA,IAAI,YAAY,UAAA,EAAY;AAC1B,UAAA,MAAM,IAAI,iBAAA;AAAA,YACR,cAAA;AAAA,YACA;AAAA,WACF;AAAA,QACF;AACA,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,CAAO,SAAA,CAAU,WAAW,CAAA;AACnD,MAAA,IAAI,OAAO,OAAA,EAAS;AAClB,QAAA,MAAM;AAAA,UACJ,IAAA,EAAM,UAAA;AAAA,UACN,QAAQ,MAAA,CAAO,IAAA;AAAA,UACf,GAAA,EAAK,WAAA;AAAA,UACL,KAAA,EAAO,SAAA;AAAA,UACP,YAAA,EAAc;AAAA,SAChB;AACA,QAAA;AAAA,MACF;AACA,MAAA,cAAA,GAAiB,MAAA,CAAO,KAAA;AAAA,IAC1B;AAEA,IAAA,MAAM,IAAI,iBAAA;AAAA,MACR,cAAA;AAAA,MACA,wCAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF,CAAA,SAAE;AAGA,IAAA,MAAM,yBAAA,CAA0B,KAAA,EAAO,IAAA,CAAK,MAAM,CAAA;AAAA,EACpD;AACF;AAcA,SAAS,sBAAA,CAA0C,MAAc,MAAA,EAAgC;AAC/F,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AAC9B,EAAA,IAAI,KAAA,GAAQ,GAAG,OAAO,MAAA;AAEtB,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,IAAI,QAAA,GAAW,KAAA;AACf,EAAA,IAAI,SAAA,GAAY,KAAA;AAChB,EAAA,IAAI,GAAA,GAAM,EAAA;AACV,EAAA,KAAA,IAAS,IAAI,KAAA,EAAO,CAAA,GAAI,IAAA,CAAK,MAAA,EAAQ,KAAK,CAAA,EAAG;AAC3C,IAAA,MAAM,EAAA,GAAK,KAAK,CAAC,CAAA;AACjB,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,SAAA,GAAY,KAAA;AACZ,MAAA;AAAA,IACF;AACA,IAAA,IAAI,EAAA,KAAO,QAAQ,QAAA,EAAU;AAC3B,MAAA,SAAA,GAAY,IAAA;AACZ,MAAA;AAAA,IACF;AACA,IAAA,IAAI,OAAO,GAAA,EAAK;AACd,MAAA,QAAA,GAAW,CAAC,QAAA;AACZ,MAAA;AAAA,IACF;AACA,IAAA,IAAI,QAAA,EAAU;AACd,IAAA,IAAI,EAAA,KAAO,KAAK,KAAA,IAAS,CAAA;AAAA,SAAA,IAChB,OAAO,GAAA,EAAK;AACnB,MAAA,KAAA,IAAS,CAAA;AACT,MAAA,IAAI,KAAA,KAAU,GAAG,GAAA,GAAM,CAAA;AAAA,IACzB;AAAA,EACF;AACA,EAAA,IAAI,GAAA,GAAM,GAAG,OAAO,MAAA;AACpB,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,KAAA,EAAO,MAAM,CAAC,CAAA;AAC3C,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,SAAS,CAAA;AAAA,EAC/B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AAGA,EAAA,MAAM,eAAgB,MAAA,CAAkD,OAAA;AACxE,EAAA,MAAM,cAAc,OAAO,YAAA,KAAiB,aAAa,YAAA,CAAa,IAAA,CAAK,MAAM,CAAA,GAAI,MAAA;AACrF,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,SAAA,CAAU,MAAM,CAAA;AAC3C,EAAA,OAAO,MAAA,CAAO,OAAA,GAAU,MAAA,CAAO,IAAA,GAAO,MAAA;AACxC","file":"chunk-DU7DE543.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 chunkYVI4YPUP_cjs = require('./chunk-YVI4YPUP.cjs');
4
- var chunkA3MHE2MQ_cjs = require('./chunk-A3MHE2MQ.cjs');
5
- var chunkBE3W4HYV_cjs = require('./chunk-BE3W4HYV.cjs');
3
+ var chunkDGLLVCNB_cjs = require('./chunk-DGLLVCNB.cjs');
4
+ var chunkIHFNRNTJ_cjs = require('./chunk-IHFNRNTJ.cjs');
5
+ var chunkBCQ3E2ZG_cjs = require('./chunk-BCQ3E2ZG.cjs');
6
6
  var fs = require('fs');
7
7
  var promises = require('fs/promises');
8
8
  var path = require('path');
@@ -26,7 +26,7 @@ function assertValidIdForStore(id) {
26
26
  /* allowReserved */
27
27
  true
28
28
  )) {
29
- throw new chunkA3MHE2MQ_cjs.InvalidTaskIdError(`store rejects invalid task id: ${id}`, id);
29
+ throw new chunkIHFNRNTJ_cjs.InvalidTaskIdError(`store rejects invalid task id: ${id}`, id);
30
30
  }
31
31
  }
32
32
  function terminalTimestamp(h) {
@@ -120,14 +120,14 @@ var JsonFileTaskStore = class {
120
120
  }
121
121
  async insert(handle) {
122
122
  assertValidIdForStore(handle.id);
123
- await chunkYVI4YPUP_cjs.atomicWriteText(this.filePath(handle.id), JSON.stringify(handle));
123
+ await chunkDGLLVCNB_cjs.atomicWriteText(this.filePath(handle.id), JSON.stringify(handle));
124
124
  }
125
125
  async update(id, mutate) {
126
126
  assertValidIdForStore(id);
127
127
  const existing = await this.get(id);
128
128
  if (existing === void 0) return void 0;
129
129
  const next = mutate(existing);
130
- await chunkYVI4YPUP_cjs.atomicWriteText(this.filePath(id), JSON.stringify(next));
130
+ await chunkDGLLVCNB_cjs.atomicWriteText(this.filePath(id), JSON.stringify(next));
131
131
  return next;
132
132
  }
133
133
  async get(id) {
@@ -138,7 +138,7 @@ var JsonFileTaskStore = class {
138
138
  } catch (err) {
139
139
  const code = err.code;
140
140
  if (code === "ENOENT") return void 0;
141
- chunkBE3W4HYV_cjs.diag(`[task-store] failed to read ${id}: ${err.message}
141
+ chunkBCQ3E2ZG_cjs.diag(`[task-store] failed to read ${id}: ${err.message}
142
142
  `);
143
143
  return void 0;
144
144
  }
@@ -193,5 +193,5 @@ exports.InMemoryTaskStore = InMemoryTaskStore;
193
193
  exports.JsonFileTaskStore = JsonFileTaskStore;
194
194
  exports.getTaskStoreFor = getTaskStoreFor;
195
195
  exports.isValidTaskId = isValidTaskId;
196
- //# sourceMappingURL=chunk-VVMLMKYZ.cjs.map
197
- //# sourceMappingURL=chunk-VVMLMKYZ.cjs.map
196
+ //# sourceMappingURL=chunk-DWY25VLP.cjs.map
197
+ //# sourceMappingURL=chunk-DWY25VLP.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types/task.ts","../src/internal/task/store.ts"],"names":["InvalidTaskIdError","mkdirSync","join","atomicWriteText","readFile","diag","readdirSync","unlink"],"mappings":"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","file":"chunk-VVMLMKYZ.cjs","sourcesContent":["/**\n * Public type contract for the Task observability registry (ADRs D361-D374).\n *\n * Tasks are an opt-in observability layer over async work in the SDK\n * (`Agent.send`, `Agent.batch`, `Workflow.run`, `Cron` fires). They have\n * a closed 5-state lifecycle (D362), discriminated events (D366), and a\n * pluggable store (D364). The `Task` facade in `task.ts` is the public\n * surface; consumers import these types from `@theokit/sdk`.\n *\n * @public\n */\n\n/**\n * Closed enum of the 5 lifecycle states (D362).\n *\n * Transitions are acyclic:\n * queued → running → (finished | error | cancelled)\n * queued → cancelled (direct, no run started)\n */\nexport type TaskState = \"queued\" | \"running\" | \"finished\" | \"error\" | \"cancelled\";\n\n/** Discriminator of the runtime that produced a task (D374). */\nexport type TaskKind = \"run\" | \"batch\" | \"workflow\" | \"cron\" | \"custom\";\n\n/** Discriminated union of task lifecycle events (D366). */\nexport type TaskEvent =\n | {\n readonly type: \"submitted\";\n readonly taskId: string;\n readonly kind: TaskKind;\n readonly submittedAt: number;\n readonly meta?: Record<string, unknown>;\n /** D372 — flag set on the first yielded event when the ring buffer was at cap. */\n readonly truncated?: boolean;\n }\n | { readonly type: \"started\"; readonly taskId: string; readonly startedAt: number }\n | {\n readonly type: \"progress\";\n readonly taskId: string;\n readonly at: number;\n readonly payload: unknown;\n }\n | {\n readonly type: \"finished\";\n readonly taskId: string;\n readonly finishedAt: number;\n readonly result: unknown;\n }\n | {\n readonly type: \"errored\";\n readonly taskId: string;\n readonly erroredAt: number;\n readonly error: { readonly code: string; readonly message: string };\n }\n | {\n readonly type: \"cancelled\";\n readonly taskId: string;\n readonly cancelledAt: number;\n readonly reason?: string;\n };\n\n/** Public read-only view of a task entry in the registry. */\nexport interface TaskHandle {\n readonly id: string;\n readonly kind: TaskKind;\n readonly state: TaskState;\n readonly submittedAt: number;\n readonly startedAt?: number;\n readonly finishedAt?: number;\n readonly cancelledAt?: number;\n readonly erroredAt?: number;\n readonly result?: unknown;\n readonly error?: { readonly code: string; readonly message: string };\n readonly meta?: Record<string, unknown>;\n /**\n * EC-7 — cross-process best-effort cancel flag. Set by CLI\n * `theokit tasks cancel` via JsonFileTaskStore. The owning process\n * polls at checkpoints and honors via AbortController. Always\n * `undefined` for in-process cancel paths (which go directly through\n * AbortController).\n */\n readonly cancelRequested?: boolean;\n}\n\n/** Query filter for `Task.list`. */\nexport interface TaskFilter {\n readonly state?: TaskState | readonly TaskState[];\n readonly kind?: TaskKind | readonly TaskKind[];\n readonly submittedAfter?: number;\n readonly submittedBefore?: number;\n /** Defaults to 100. JsonFileTaskStore hard-caps loaded entries at 256 (D364). */\n readonly limit?: number;\n}\n\n/** Options for `Task.submit`. */\nexport interface TaskSubmitOptions {\n /**\n * Optional user-supplied ID. Must match grammar `^[a-z0-9][a-z0-9_-]*$`\n * and MUST NOT start with the reserved prefixes `wf-` / `b-` / `cron-`\n * (D368, EC-5). When omitted, `crypto.randomUUID()` is used.\n */\n readonly id?: string;\n readonly meta?: Record<string, unknown>;\n /**\n * Optional caller-provided AbortSignal. If already aborted at submit\n * time, the registry short-circuits to `cancelled` without acquiring\n * a semaphore slot (EC-4).\n */\n readonly signal?: AbortSignal;\n /**\n * SE2 — an opt-in {@link import(\"./run-events.js\").RunEventSink}. The task's\n * lifecycle is forwarded to it as typed `task_started` / `task_updated` /\n * `task_completed` RunEvents, so a caller that spawned the task can observe it\n * through the same `onRunEvent` channel as the rest of the run. Best-effort (a\n * throwing sink never breaks the task). The dedicated `Task.subscribe(id)`\n * channel is unaffected.\n */\n readonly onRunEvent?: import(\"./run-events.js\").RunEventSink;\n}\n\n/** Options shape for `TaskStore` factory (D364). */\nexport type TaskStoreOptions =\n | { readonly backend: \"memory\" }\n | { readonly backend: \"json\"; readonly dir: string };\n\n/** Result of `Task.cancel` (D365 — idempotent). */\nexport interface TaskCancelResult {\n readonly cancelled: boolean;\n readonly alreadyTerminal: boolean;\n}\n\n/**\n * Grammar for user-supplied task IDs (D368).\n * `crypto.randomUUID()` outputs do NOT match this (UUIDs have dashes\n * AND uppercase letters in their canonical form on some Node versions),\n * but the registry normalizes auto-generated IDs to lowercase before\n * insertion, so they pass the same regex.\n */\nconst TASK_ID_GRAMMAR = /^[a-z0-9][a-z0-9_-]*$/;\n\n/** Reserved prefixes for adapter-generated IDs (D368, EC-5). */\nconst RESERVED_PREFIXES = [\"wf-\", \"b-\", \"cron-\"] as const;\n\n/**\n * Validates a task ID against the public grammar + reserved prefixes.\n * Throws `InvalidTaskIdError` from `../errors.js` on rejection.\n *\n * Adapter callers (workflow/batch/cron) MUST set `allowReserved: true`\n * to register their own IDs; user-facing surfaces (`Task.submit`,\n * `agent.send({ task: { id } })`) leave it false.\n */\nexport function isValidTaskId(id: string, allowReserved: boolean): boolean {\n if (!TASK_ID_GRAMMAR.test(id)) return false;\n if (allowReserved) return true;\n for (const prefix of RESERVED_PREFIXES) {\n if (id.startsWith(prefix)) return false;\n }\n return true;\n}\n\n/** Re-exported for adapter implementations + tests. */\nexport const TASK_RESERVED_PREFIXES: readonly string[] = RESERVED_PREFIXES;\n","/**\n * `TaskStore` interface + 2 implementations (ADR D364).\n *\n * - `InMemoryTaskStore` — default, transient, single-process.\n * - `JsonFileTaskStore` — opt-in, one JSON file per task under a\n * dedicated dir; single-process invariant (EC-15 documented).\n *\n * Edge cases absorbed:\n * - EC-1: constructor auto-creates dir (mkdirSync recursive idempotent).\n * - EC-2: every method validates the task id against the public\n * grammar (D368) BEFORE doing any path I/O — path-traversal defense.\n * - EC-6: `list()` returns `[]` on ENOENT (fresh install path).\n * - EC-8: `list()` skips `.tmp.*` orphan files left by interrupted\n * atomic writes.\n * - EC-14 (DOCUMENT): `list()` JSDoc documents the 256-row hard cap\n * and the `submittedBefore` paging idiom.\n * - EC-15 (DOCUMENT): `JsonFileTaskStore` JSDoc documents the\n * single-process invariant; v0.2 SQLite covers cross-process.\n *\n * @internal\n */\n\nimport { mkdirSync, readdirSync } from \"node:fs\";\nimport { readFile, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { InvalidTaskIdError } from \"../../errors.js\";\nimport {\n isValidTaskId,\n type TaskFilter,\n type TaskHandle,\n type TaskState,\n type TaskStoreOptions,\n} from \"../../types/task.js\";\nimport { diag } from \"../diagnostics.js\";\nimport { atomicWriteText } from \"../persistence/atomic-write.js\";\n\nconst JSON_LOAD_CAP = 256;\nconst DEFAULT_LIST_LIMIT = 100;\n\n/** Storage interface used by `TaskRegistry`. */\nexport interface TaskStore {\n insert(handle: TaskHandle): Promise<void>;\n update(id: string, mutate: (h: TaskHandle) => TaskHandle): Promise<TaskHandle | undefined>;\n get(id: string): Promise<TaskHandle | undefined>;\n /**\n * Returns at most `filter.limit ?? 100` matching handles. JsonFile\n * backend hard-caps loaded entries at 256 — callers needing larger\n * pages must use `submittedBefore` to walk the timeline.\n */\n list(filter: TaskFilter): Promise<TaskHandle[]>;\n delete(id: string): Promise<boolean>;\n /** Removes terminal handles whose terminal-timestamp is older than `epochMs`. */\n evictTerminalOlderThan(epochMs: number): Promise<number>;\n}\n\nfunction assertValidIdForStore(id: string): void {\n if (!isValidTaskId(id, /* allowReserved */ true)) {\n throw new InvalidTaskIdError(`store rejects invalid task id: ${id}`, id);\n }\n}\n\nfunction terminalTimestamp(h: TaskHandle): number | undefined {\n if (h.state === \"finished\") return h.finishedAt;\n if (h.state === \"error\") return h.erroredAt;\n if (h.state === \"cancelled\") return h.cancelledAt;\n return undefined;\n}\n\nfunction isTerminal(state: TaskState): boolean {\n return state === \"finished\" || state === \"error\" || state === \"cancelled\";\n}\n\nfunction matchesState(h: TaskHandle, filter: TaskFilter): boolean {\n if (filter.state === undefined) return true;\n const states = Array.isArray(filter.state) ? filter.state : [filter.state];\n return states.includes(h.state);\n}\nfunction matchesKind(h: TaskHandle, filter: TaskFilter): boolean {\n if (filter.kind === undefined) return true;\n const kinds = Array.isArray(filter.kind) ? filter.kind : [filter.kind];\n return kinds.includes(h.kind);\n}\nfunction matchesTime(h: TaskHandle, filter: TaskFilter): boolean {\n if (filter.submittedAfter !== undefined && h.submittedAt <= filter.submittedAfter) return false;\n if (filter.submittedBefore !== undefined && h.submittedAt >= filter.submittedBefore) return false;\n return true;\n}\nfunction matchesFilter(h: TaskHandle, filter: TaskFilter): boolean {\n return matchesState(h, filter) && matchesKind(h, filter) && matchesTime(h, filter);\n}\n\nfunction applyFilter(values: Iterable<TaskHandle>, filter: TaskFilter): TaskHandle[] {\n const limit = filter.limit ?? DEFAULT_LIST_LIMIT;\n const out: TaskHandle[] = [];\n for (const h of values) {\n if (matchesFilter(h, filter)) {\n out.push(h);\n if (out.length >= limit) break;\n }\n }\n return out;\n}\n\n/* ─── InMemory ─── */\n\nexport class InMemoryTaskStore implements TaskStore {\n private readonly map = new Map<string, TaskHandle>();\n\n async insert(handle: TaskHandle): Promise<void> {\n assertValidIdForStore(handle.id);\n this.map.set(handle.id, handle);\n }\n\n async update(id: string, mutate: (h: TaskHandle) => TaskHandle): Promise<TaskHandle | undefined> {\n assertValidIdForStore(id);\n const existing = this.map.get(id);\n if (existing === undefined) return undefined;\n const next = mutate(existing);\n this.map.set(id, next);\n return next;\n }\n\n async get(id: string): Promise<TaskHandle | undefined> {\n assertValidIdForStore(id);\n return this.map.get(id);\n }\n\n async list(filter: TaskFilter): Promise<TaskHandle[]> {\n return applyFilter(this.map.values(), filter);\n }\n\n async delete(id: string): Promise<boolean> {\n assertValidIdForStore(id);\n return this.map.delete(id);\n }\n\n async evictTerminalOlderThan(epochMs: number): Promise<number> {\n let count = 0;\n for (const [id, h] of this.map.entries()) {\n if (!isTerminal(h.state)) continue;\n const ts = terminalTimestamp(h);\n if (ts !== undefined && ts < epochMs) {\n this.map.delete(id);\n count++;\n }\n }\n return count;\n }\n}\n\n/* ─── JsonFile (opt-in) ───\n *\n * IMPORTANT (EC-15): `JsonFileTaskStore` is **single-process**.\n * Concurrent writers from multiple Node processes against the same\n * directory may corrupt entries (atomic-write protects per-file, but\n * the `list()` scan + `update()` read-modify-write cycle is not\n * serialised across processes). Use only when the `TaskRegistry`\n * runs in exactly one process. v0.2 will add a SQLite backend with\n * the same interface for cross-process scenarios (D364 + D61).\n */\nexport class JsonFileTaskStore implements TaskStore {\n constructor(private readonly dir: string) {\n // EC-1: idempotent mkdir; ignore EEXIST.\n try {\n mkdirSync(dir, { recursive: true });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"EEXIST\") throw err;\n }\n }\n\n private filePath(id: string): string {\n return join(this.dir, `${id}.json`);\n }\n\n async insert(handle: TaskHandle): Promise<void> {\n assertValidIdForStore(handle.id);\n await atomicWriteText(this.filePath(handle.id), JSON.stringify(handle));\n }\n\n async update(id: string, mutate: (h: TaskHandle) => TaskHandle): Promise<TaskHandle | undefined> {\n assertValidIdForStore(id);\n const existing = await this.get(id);\n if (existing === undefined) return undefined;\n const next = mutate(existing);\n await atomicWriteText(this.filePath(id), JSON.stringify(next));\n return next;\n }\n\n async get(id: string): Promise<TaskHandle | undefined> {\n assertValidIdForStore(id);\n try {\n const raw = await readFile(this.filePath(id), \"utf8\");\n return JSON.parse(raw) as TaskHandle;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") return undefined;\n // Corrupt JSON or other I/O error — log + degrade gracefully (D50/EC-7 cache pattern).\n diag(`[task-store] failed to read ${id}: ${(err as Error).message}\\n`);\n return undefined;\n }\n }\n\n async list(filter: TaskFilter): Promise<TaskHandle[]> {\n let entries: string[];\n try {\n entries = readdirSync(this.dir);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return []; // EC-6\n throw err;\n }\n // EC-8: skip orphan .tmp files left by interrupted atomic writes.\n const candidates = entries\n .filter((name) => name.endsWith(\".json\") && !name.includes(\".tmp\"))\n .slice(0, JSON_LOAD_CAP);\n\n const loaded = await Promise.all(\n candidates.map(async (name) => {\n const id = name.slice(0, -\".json\".length);\n if (!isValidTaskId(id, true)) return undefined;\n return this.get(id);\n }),\n );\n const handles = loaded.filter((h): h is TaskHandle => h !== undefined);\n return applyFilter(handles, filter);\n }\n\n async delete(id: string): Promise<boolean> {\n assertValidIdForStore(id);\n try {\n await unlink(this.filePath(id));\n return true;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n throw err;\n }\n }\n\n async evictTerminalOlderThan(epochMs: number): Promise<number> {\n const handles = await this.list({ state: [\"finished\", \"error\", \"cancelled\"], limit: 256 });\n let count = 0;\n for (const h of handles) {\n const ts = terminalTimestamp(h);\n if (ts !== undefined && ts < epochMs) {\n if (await this.delete(h.id)) count++;\n }\n }\n return count;\n }\n}\n\n/** Factory used by `TaskRegistry.configure` (D364). */\nexport function getTaskStoreFor(options: TaskStoreOptions): TaskStore {\n if (options.backend === \"memory\") return new InMemoryTaskStore();\n return new JsonFileTaskStore(options.dir);\n}\n"]}
1
+ {"version":3,"sources":["../src/types/task.ts","../src/internal/task/store.ts"],"names":["InvalidTaskIdError","mkdirSync","join","atomicWriteText","readFile","diag","readdirSync","unlink"],"mappings":"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","file":"chunk-DWY25VLP.cjs","sourcesContent":["/**\n * Public type contract for the Task observability registry (ADRs D361-D374).\n *\n * Tasks are an opt-in observability layer over async work in the SDK\n * (`Agent.send`, `Agent.batch`, `Workflow.run`, `Cron` fires). They have\n * a closed 5-state lifecycle (D362), discriminated events (D366), and a\n * pluggable store (D364). The `Task` facade in `task.ts` is the public\n * surface; consumers import these types from `@theokit/sdk`.\n *\n * @public\n */\n\n/**\n * Closed enum of the 5 lifecycle states (D362).\n *\n * Transitions are acyclic:\n * queued → running → (finished | error | cancelled)\n * queued → cancelled (direct, no run started)\n */\nexport type TaskState = \"queued\" | \"running\" | \"finished\" | \"error\" | \"cancelled\";\n\n/** Discriminator of the runtime that produced a task (D374). */\nexport type TaskKind = \"run\" | \"batch\" | \"workflow\" | \"cron\" | \"custom\";\n\n/** Discriminated union of task lifecycle events (D366). */\nexport type TaskEvent =\n | {\n readonly type: \"submitted\";\n readonly taskId: string;\n readonly kind: TaskKind;\n readonly submittedAt: number;\n readonly meta?: Record<string, unknown>;\n /** D372 — flag set on the first yielded event when the ring buffer was at cap. */\n readonly truncated?: boolean;\n }\n | { readonly type: \"started\"; readonly taskId: string; readonly startedAt: number }\n | {\n readonly type: \"progress\";\n readonly taskId: string;\n readonly at: number;\n readonly payload: unknown;\n }\n | {\n readonly type: \"finished\";\n readonly taskId: string;\n readonly finishedAt: number;\n readonly result: unknown;\n }\n | {\n readonly type: \"errored\";\n readonly taskId: string;\n readonly erroredAt: number;\n readonly error: { readonly code: string; readonly message: string };\n }\n | {\n readonly type: \"cancelled\";\n readonly taskId: string;\n readonly cancelledAt: number;\n readonly reason?: string;\n };\n\n/** Public read-only view of a task entry in the registry. */\nexport interface TaskHandle {\n readonly id: string;\n readonly kind: TaskKind;\n readonly state: TaskState;\n readonly submittedAt: number;\n readonly startedAt?: number;\n readonly finishedAt?: number;\n readonly cancelledAt?: number;\n readonly erroredAt?: number;\n readonly result?: unknown;\n readonly error?: { readonly code: string; readonly message: string };\n readonly meta?: Record<string, unknown>;\n /**\n * EC-7 — cross-process best-effort cancel flag. Set by CLI\n * `theokit tasks cancel` via JsonFileTaskStore. The owning process\n * polls at checkpoints and honors via AbortController. Always\n * `undefined` for in-process cancel paths (which go directly through\n * AbortController).\n */\n readonly cancelRequested?: boolean;\n}\n\n/** Query filter for `Task.list`. */\nexport interface TaskFilter {\n readonly state?: TaskState | readonly TaskState[];\n readonly kind?: TaskKind | readonly TaskKind[];\n readonly submittedAfter?: number;\n readonly submittedBefore?: number;\n /** Defaults to 100. JsonFileTaskStore hard-caps loaded entries at 256 (D364). */\n readonly limit?: number;\n}\n\n/** Options for `Task.submit`. */\nexport interface TaskSubmitOptions {\n /**\n * Optional user-supplied ID. Must match grammar `^[a-z0-9][a-z0-9_-]*$`\n * and MUST NOT start with the reserved prefixes `wf-` / `b-` / `cron-`\n * (D368, EC-5). When omitted, `crypto.randomUUID()` is used.\n */\n readonly id?: string;\n readonly meta?: Record<string, unknown>;\n /**\n * Optional caller-provided AbortSignal. If already aborted at submit\n * time, the registry short-circuits to `cancelled` without acquiring\n * a semaphore slot (EC-4).\n */\n readonly signal?: AbortSignal;\n /**\n * SE2 — an opt-in {@link import(\"./run-events.js\").RunEventSink}. The task's\n * lifecycle is forwarded to it as typed `task_started` / `task_updated` /\n * `task_completed` RunEvents, so a caller that spawned the task can observe it\n * through the same `onRunEvent` channel as the rest of the run. Best-effort (a\n * throwing sink never breaks the task). The dedicated `Task.subscribe(id)`\n * channel is unaffected.\n */\n readonly onRunEvent?: import(\"./run-events.js\").RunEventSink;\n}\n\n/** Options shape for `TaskStore` factory (D364). */\nexport type TaskStoreOptions =\n | { readonly backend: \"memory\" }\n | { readonly backend: \"json\"; readonly dir: string };\n\n/** Result of `Task.cancel` (D365 — idempotent). */\nexport interface TaskCancelResult {\n readonly cancelled: boolean;\n readonly alreadyTerminal: boolean;\n}\n\n/**\n * Grammar for user-supplied task IDs (D368).\n * `crypto.randomUUID()` outputs do NOT match this (UUIDs have dashes\n * AND uppercase letters in their canonical form on some Node versions),\n * but the registry normalizes auto-generated IDs to lowercase before\n * insertion, so they pass the same regex.\n */\nconst TASK_ID_GRAMMAR = /^[a-z0-9][a-z0-9_-]*$/;\n\n/** Reserved prefixes for adapter-generated IDs (D368, EC-5). */\nconst RESERVED_PREFIXES = [\"wf-\", \"b-\", \"cron-\"] as const;\n\n/**\n * Validates a task ID against the public grammar + reserved prefixes.\n * Throws `InvalidTaskIdError` from `../errors.js` on rejection.\n *\n * Adapter callers (workflow/batch/cron) MUST set `allowReserved: true`\n * to register their own IDs; user-facing surfaces (`Task.submit`,\n * `agent.send({ task: { id } })`) leave it false.\n */\nexport function isValidTaskId(id: string, allowReserved: boolean): boolean {\n if (!TASK_ID_GRAMMAR.test(id)) return false;\n if (allowReserved) return true;\n for (const prefix of RESERVED_PREFIXES) {\n if (id.startsWith(prefix)) return false;\n }\n return true;\n}\n\n/** Re-exported for adapter implementations + tests. */\nexport const TASK_RESERVED_PREFIXES: readonly string[] = RESERVED_PREFIXES;\n","/**\n * `TaskStore` interface + 2 implementations (ADR D364).\n *\n * - `InMemoryTaskStore` — default, transient, single-process.\n * - `JsonFileTaskStore` — opt-in, one JSON file per task under a\n * dedicated dir; single-process invariant (EC-15 documented).\n *\n * Edge cases absorbed:\n * - EC-1: constructor auto-creates dir (mkdirSync recursive idempotent).\n * - EC-2: every method validates the task id against the public\n * grammar (D368) BEFORE doing any path I/O — path-traversal defense.\n * - EC-6: `list()` returns `[]` on ENOENT (fresh install path).\n * - EC-8: `list()` skips `.tmp.*` orphan files left by interrupted\n * atomic writes.\n * - EC-14 (DOCUMENT): `list()` JSDoc documents the 256-row hard cap\n * and the `submittedBefore` paging idiom.\n * - EC-15 (DOCUMENT): `JsonFileTaskStore` JSDoc documents the\n * single-process invariant; v0.2 SQLite covers cross-process.\n *\n * @internal\n */\n\nimport { mkdirSync, readdirSync } from \"node:fs\";\nimport { readFile, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { InvalidTaskIdError } from \"../../errors.js\";\nimport {\n isValidTaskId,\n type TaskFilter,\n type TaskHandle,\n type TaskState,\n type TaskStoreOptions,\n} from \"../../types/task.js\";\nimport { diag } from \"../diagnostics.js\";\nimport { atomicWriteText } from \"../persistence/atomic-write.js\";\n\nconst JSON_LOAD_CAP = 256;\nconst DEFAULT_LIST_LIMIT = 100;\n\n/** Storage interface used by `TaskRegistry`. */\nexport interface TaskStore {\n insert(handle: TaskHandle): Promise<void>;\n update(id: string, mutate: (h: TaskHandle) => TaskHandle): Promise<TaskHandle | undefined>;\n get(id: string): Promise<TaskHandle | undefined>;\n /**\n * Returns at most `filter.limit ?? 100` matching handles. JsonFile\n * backend hard-caps loaded entries at 256 — callers needing larger\n * pages must use `submittedBefore` to walk the timeline.\n */\n list(filter: TaskFilter): Promise<TaskHandle[]>;\n delete(id: string): Promise<boolean>;\n /** Removes terminal handles whose terminal-timestamp is older than `epochMs`. */\n evictTerminalOlderThan(epochMs: number): Promise<number>;\n}\n\nfunction assertValidIdForStore(id: string): void {\n if (!isValidTaskId(id, /* allowReserved */ true)) {\n throw new InvalidTaskIdError(`store rejects invalid task id: ${id}`, id);\n }\n}\n\nfunction terminalTimestamp(h: TaskHandle): number | undefined {\n if (h.state === \"finished\") return h.finishedAt;\n if (h.state === \"error\") return h.erroredAt;\n if (h.state === \"cancelled\") return h.cancelledAt;\n return undefined;\n}\n\nfunction isTerminal(state: TaskState): boolean {\n return state === \"finished\" || state === \"error\" || state === \"cancelled\";\n}\n\nfunction matchesState(h: TaskHandle, filter: TaskFilter): boolean {\n if (filter.state === undefined) return true;\n const states = Array.isArray(filter.state) ? filter.state : [filter.state];\n return states.includes(h.state);\n}\nfunction matchesKind(h: TaskHandle, filter: TaskFilter): boolean {\n if (filter.kind === undefined) return true;\n const kinds = Array.isArray(filter.kind) ? filter.kind : [filter.kind];\n return kinds.includes(h.kind);\n}\nfunction matchesTime(h: TaskHandle, filter: TaskFilter): boolean {\n if (filter.submittedAfter !== undefined && h.submittedAt <= filter.submittedAfter) return false;\n if (filter.submittedBefore !== undefined && h.submittedAt >= filter.submittedBefore) return false;\n return true;\n}\nfunction matchesFilter(h: TaskHandle, filter: TaskFilter): boolean {\n return matchesState(h, filter) && matchesKind(h, filter) && matchesTime(h, filter);\n}\n\nfunction applyFilter(values: Iterable<TaskHandle>, filter: TaskFilter): TaskHandle[] {\n const limit = filter.limit ?? DEFAULT_LIST_LIMIT;\n const out: TaskHandle[] = [];\n for (const h of values) {\n if (matchesFilter(h, filter)) {\n out.push(h);\n if (out.length >= limit) break;\n }\n }\n return out;\n}\n\n/* ─── InMemory ─── */\n\nexport class InMemoryTaskStore implements TaskStore {\n private readonly map = new Map<string, TaskHandle>();\n\n async insert(handle: TaskHandle): Promise<void> {\n assertValidIdForStore(handle.id);\n this.map.set(handle.id, handle);\n }\n\n async update(id: string, mutate: (h: TaskHandle) => TaskHandle): Promise<TaskHandle | undefined> {\n assertValidIdForStore(id);\n const existing = this.map.get(id);\n if (existing === undefined) return undefined;\n const next = mutate(existing);\n this.map.set(id, next);\n return next;\n }\n\n async get(id: string): Promise<TaskHandle | undefined> {\n assertValidIdForStore(id);\n return this.map.get(id);\n }\n\n async list(filter: TaskFilter): Promise<TaskHandle[]> {\n return applyFilter(this.map.values(), filter);\n }\n\n async delete(id: string): Promise<boolean> {\n assertValidIdForStore(id);\n return this.map.delete(id);\n }\n\n async evictTerminalOlderThan(epochMs: number): Promise<number> {\n let count = 0;\n for (const [id, h] of this.map.entries()) {\n if (!isTerminal(h.state)) continue;\n const ts = terminalTimestamp(h);\n if (ts !== undefined && ts < epochMs) {\n this.map.delete(id);\n count++;\n }\n }\n return count;\n }\n}\n\n/* ─── JsonFile (opt-in) ───\n *\n * IMPORTANT (EC-15): `JsonFileTaskStore` is **single-process**.\n * Concurrent writers from multiple Node processes against the same\n * directory may corrupt entries (atomic-write protects per-file, but\n * the `list()` scan + `update()` read-modify-write cycle is not\n * serialised across processes). Use only when the `TaskRegistry`\n * runs in exactly one process. v0.2 will add a SQLite backend with\n * the same interface for cross-process scenarios (D364 + D61).\n */\nexport class JsonFileTaskStore implements TaskStore {\n constructor(private readonly dir: string) {\n // EC-1: idempotent mkdir; ignore EEXIST.\n try {\n mkdirSync(dir, { recursive: true });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"EEXIST\") throw err;\n }\n }\n\n private filePath(id: string): string {\n return join(this.dir, `${id}.json`);\n }\n\n async insert(handle: TaskHandle): Promise<void> {\n assertValidIdForStore(handle.id);\n await atomicWriteText(this.filePath(handle.id), JSON.stringify(handle));\n }\n\n async update(id: string, mutate: (h: TaskHandle) => TaskHandle): Promise<TaskHandle | undefined> {\n assertValidIdForStore(id);\n const existing = await this.get(id);\n if (existing === undefined) return undefined;\n const next = mutate(existing);\n await atomicWriteText(this.filePath(id), JSON.stringify(next));\n return next;\n }\n\n async get(id: string): Promise<TaskHandle | undefined> {\n assertValidIdForStore(id);\n try {\n const raw = await readFile(this.filePath(id), \"utf8\");\n return JSON.parse(raw) as TaskHandle;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") return undefined;\n // Corrupt JSON or other I/O error — log + degrade gracefully (D50/EC-7 cache pattern).\n diag(`[task-store] failed to read ${id}: ${(err as Error).message}\\n`);\n return undefined;\n }\n }\n\n async list(filter: TaskFilter): Promise<TaskHandle[]> {\n let entries: string[];\n try {\n entries = readdirSync(this.dir);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return []; // EC-6\n throw err;\n }\n // EC-8: skip orphan .tmp files left by interrupted atomic writes.\n const candidates = entries\n .filter((name) => name.endsWith(\".json\") && !name.includes(\".tmp\"))\n .slice(0, JSON_LOAD_CAP);\n\n const loaded = await Promise.all(\n candidates.map(async (name) => {\n const id = name.slice(0, -\".json\".length);\n if (!isValidTaskId(id, true)) return undefined;\n return this.get(id);\n }),\n );\n const handles = loaded.filter((h): h is TaskHandle => h !== undefined);\n return applyFilter(handles, filter);\n }\n\n async delete(id: string): Promise<boolean> {\n assertValidIdForStore(id);\n try {\n await unlink(this.filePath(id));\n return true;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n throw err;\n }\n }\n\n async evictTerminalOlderThan(epochMs: number): Promise<number> {\n const handles = await this.list({ state: [\"finished\", \"error\", \"cancelled\"], limit: 256 });\n let count = 0;\n for (const h of handles) {\n const ts = terminalTimestamp(h);\n if (ts !== undefined && ts < epochMs) {\n if (await this.delete(h.id)) count++;\n }\n }\n return count;\n }\n}\n\n/** Factory used by `TaskRegistry.configure` (D364). */\nexport function getTaskStoreFor(options: TaskStoreOptions): TaskStore {\n if (options.backend === \"memory\") return new InMemoryTaskStore();\n return new JsonFileTaskStore(options.dir);\n}\n"]}