@theokit/sdk 4.24.0 → 4.26.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 (382) hide show
  1. package/dist/a2a/index.cjs +10 -171
  2. package/dist/a2a/index.cjs.map +1 -1
  3. package/dist/a2a/index.js +3 -170
  4. package/dist/a2a/index.js.map +1 -1
  5. package/dist/agent-factory-registry-UU46BUMU.cjs +16 -0
  6. package/dist/agent-factory-registry-UU46BUMU.cjs.map +1 -0
  7. package/dist/agent-factory-registry-ZVTABLEY.js +3 -0
  8. package/dist/agent-factory-registry-ZVTABLEY.js.map +1 -0
  9. package/dist/auth/index.cjs +63 -367
  10. package/dist/auth/index.cjs.map +1 -1
  11. package/dist/auth/index.js +6 -342
  12. package/dist/auth/index.js.map +1 -1
  13. package/dist/batch-2FSD2UNL.cjs +244 -0
  14. package/dist/batch-2FSD2UNL.cjs.map +1 -0
  15. package/dist/batch-MR2HKYMS.js +241 -0
  16. package/dist/batch-MR2HKYMS.js.map +1 -0
  17. package/dist/chunk-2HRYBRD7.cjs +31 -0
  18. package/dist/chunk-2HRYBRD7.cjs.map +1 -0
  19. package/dist/chunk-2MF3IE2D.cjs +2863 -0
  20. package/dist/chunk-2MF3IE2D.cjs.map +1 -0
  21. package/dist/chunk-2ONFGMBV.js +6 -0
  22. package/dist/chunk-2ONFGMBV.js.map +1 -0
  23. package/dist/chunk-2SFBB54R.js +23 -0
  24. package/dist/chunk-2SFBB54R.js.map +1 -0
  25. package/dist/chunk-2XLKLVVR.js +18 -0
  26. package/dist/chunk-2XLKLVVR.js.map +1 -0
  27. package/dist/chunk-4SXHEZIV.cjs +240 -0
  28. package/dist/chunk-4SXHEZIV.cjs.map +1 -0
  29. package/dist/chunk-4VPXM6UU.js +10 -0
  30. package/dist/chunk-4VPXM6UU.js.map +1 -0
  31. package/dist/chunk-4WL52CXU.cjs +148 -0
  32. package/dist/chunk-4WL52CXU.cjs.map +1 -0
  33. package/dist/chunk-5NBUH3NO.js +39 -0
  34. package/dist/chunk-5NBUH3NO.js.map +1 -0
  35. package/dist/chunk-5PZMMF4H.js +43 -0
  36. package/dist/chunk-5PZMMF4H.js.map +1 -0
  37. package/dist/chunk-6CLRANZA.js +289 -0
  38. package/dist/chunk-6CLRANZA.js.map +1 -0
  39. package/dist/chunk-6JSIEDKL.cjs +121 -0
  40. package/dist/chunk-6JSIEDKL.cjs.map +1 -0
  41. package/dist/chunk-6M4ODB2V.cjs +145 -0
  42. package/dist/chunk-6M4ODB2V.cjs.map +1 -0
  43. package/dist/chunk-6X6ID4MO.js +20 -0
  44. package/dist/chunk-6X6ID4MO.js.map +1 -0
  45. package/dist/chunk-77FOZCOT.js +165 -0
  46. package/dist/chunk-77FOZCOT.js.map +1 -0
  47. package/dist/chunk-7AD3ZTZL.js +25 -0
  48. package/dist/chunk-7AD3ZTZL.js.map +1 -0
  49. package/dist/chunk-7GFX45DD.js +57 -0
  50. package/dist/chunk-7GFX45DD.js.map +1 -0
  51. package/dist/chunk-7S7KKUO6.cjs +45 -0
  52. package/dist/chunk-7S7KKUO6.cjs.map +1 -0
  53. package/dist/chunk-7W7ZWMLQ.js +99 -0
  54. package/dist/chunk-7W7ZWMLQ.js.map +1 -0
  55. package/dist/chunk-A44COQJJ.cjs +353 -0
  56. package/dist/chunk-A44COQJJ.cjs.map +1 -0
  57. package/dist/chunk-AKSBP7OO.js +185 -0
  58. package/dist/chunk-AKSBP7OO.js.map +1 -0
  59. package/dist/chunk-ANIZEWTU.cjs +196 -0
  60. package/dist/chunk-ANIZEWTU.cjs.map +1 -0
  61. package/dist/chunk-BEURCLDV.cjs +139 -0
  62. package/dist/chunk-BEURCLDV.cjs.map +1 -0
  63. package/dist/chunk-BFWPZMG7.js +379 -0
  64. package/dist/chunk-BFWPZMG7.js.map +1 -0
  65. package/dist/chunk-BUUUWQMB.cjs +34 -0
  66. package/dist/chunk-BUUUWQMB.cjs.map +1 -0
  67. package/dist/chunk-BV2MWEMV.cjs +26 -0
  68. package/dist/chunk-BV2MWEMV.cjs.map +1 -0
  69. package/dist/chunk-BWT67BI4.cjs +268 -0
  70. package/dist/chunk-BWT67BI4.cjs.map +1 -0
  71. package/dist/chunk-BXV2QUIC.js +191 -0
  72. package/dist/chunk-BXV2QUIC.js.map +1 -0
  73. package/dist/chunk-C6Y6CWYD.cjs +44 -0
  74. package/dist/chunk-C6Y6CWYD.cjs.map +1 -0
  75. package/dist/chunk-C7PICHRF.cjs +68 -0
  76. package/dist/chunk-C7PICHRF.cjs.map +1 -0
  77. package/dist/chunk-CAH3G4IS.js +13 -0
  78. package/dist/chunk-CAH3G4IS.js.map +1 -0
  79. package/dist/chunk-D42XHI4O.cjs +565 -0
  80. package/dist/chunk-D42XHI4O.cjs.map +1 -0
  81. package/dist/chunk-DGRZNMTU.js +104 -0
  82. package/dist/chunk-DGRZNMTU.js.map +1 -0
  83. package/dist/chunk-DUK5WMKJ.js +71 -0
  84. package/dist/chunk-DUK5WMKJ.js.map +1 -0
  85. package/dist/chunk-EEZ7CFMM.js +14 -0
  86. package/dist/chunk-EEZ7CFMM.js.map +1 -0
  87. package/dist/chunk-EPYZOCOL.cjs +82 -0
  88. package/dist/chunk-EPYZOCOL.cjs.map +1 -0
  89. package/dist/chunk-EVADEGM7.cjs +168 -0
  90. package/dist/chunk-EVADEGM7.cjs.map +1 -0
  91. package/dist/chunk-FD2UT76F.js +3 -0
  92. package/dist/chunk-FD2UT76F.js.map +1 -0
  93. package/dist/chunk-FV3YEMQ7.js +179 -0
  94. package/dist/chunk-FV3YEMQ7.js.map +1 -0
  95. package/dist/chunk-G2F67XUR.cjs +184 -0
  96. package/dist/chunk-G2F67XUR.cjs.map +1 -0
  97. package/dist/chunk-G6GO6BXD.js +994 -0
  98. package/dist/chunk-G6GO6BXD.js.map +1 -0
  99. package/dist/chunk-GIW4L6HY.cjs +27 -0
  100. package/dist/chunk-GIW4L6HY.cjs.map +1 -0
  101. package/dist/chunk-GJAGKFTR.js +74 -0
  102. package/dist/chunk-GJAGKFTR.js.map +1 -0
  103. package/dist/chunk-HFPGOTVF.cjs +324 -0
  104. package/dist/chunk-HFPGOTVF.cjs.map +1 -0
  105. package/dist/chunk-HRA3CPGG.js +486 -0
  106. package/dist/chunk-HRA3CPGG.js.map +1 -0
  107. package/dist/chunk-HZQEDNF6.js +66 -0
  108. package/dist/chunk-HZQEDNF6.js.map +1 -0
  109. package/dist/chunk-IT3PWBW4.cjs +19 -0
  110. package/dist/chunk-IT3PWBW4.cjs.map +1 -0
  111. package/dist/chunk-JD74LN7R.cjs +171 -0
  112. package/dist/chunk-JD74LN7R.cjs.map +1 -0
  113. package/dist/chunk-JTFYYKDT.js +135 -0
  114. package/dist/chunk-JTFYYKDT.js.map +1 -0
  115. package/dist/chunk-K2BQQ445.js +30 -0
  116. package/dist/chunk-K2BQQ445.js.map +1 -0
  117. package/dist/chunk-KAP4GJHO.js +546 -0
  118. package/dist/chunk-KAP4GJHO.js.map +1 -0
  119. package/dist/chunk-KDNBTPY2.js +458 -0
  120. package/dist/chunk-KDNBTPY2.js.map +1 -0
  121. package/dist/chunk-KIO7QFIV.cjs +223 -0
  122. package/dist/chunk-KIO7QFIV.cjs.map +1 -0
  123. package/dist/chunk-KSKU6JY6.cjs +71 -0
  124. package/dist/chunk-KSKU6JY6.cjs.map +1 -0
  125. package/dist/chunk-LSLPF6OI.cjs +192 -0
  126. package/dist/chunk-LSLPF6OI.cjs.map +1 -0
  127. package/dist/chunk-LU7VALW5.js +312 -0
  128. package/dist/chunk-LU7VALW5.js.map +1 -0
  129. package/dist/chunk-LUSXDZPV.cjs +296 -0
  130. package/dist/chunk-LUSXDZPV.cjs.map +1 -0
  131. package/dist/chunk-M72RJVPC.js +69 -0
  132. package/dist/chunk-M72RJVPC.js.map +1 -0
  133. package/dist/chunk-MQLCZ4HJ.cjs +1010 -0
  134. package/dist/chunk-MQLCZ4HJ.cjs.map +1 -0
  135. package/dist/chunk-MUUQ2WFJ.cjs +4 -0
  136. package/dist/chunk-MUUQ2WFJ.cjs.map +1 -0
  137. package/dist/chunk-MZ5ZRORA.cjs +496 -0
  138. package/dist/chunk-MZ5ZRORA.cjs.map +1 -0
  139. package/dist/chunk-N24XBYNX.cjs +140 -0
  140. package/dist/chunk-N24XBYNX.cjs.map +1 -0
  141. package/dist/chunk-NINIJCHU.cjs +23 -0
  142. package/dist/chunk-NINIJCHU.cjs.map +1 -0
  143. package/dist/chunk-NRSH7RJY.js +2841 -0
  144. package/dist/chunk-NRSH7RJY.js.map +1 -0
  145. package/dist/chunk-OIYQBUW4.cjs +111 -0
  146. package/dist/chunk-OIYQBUW4.cjs.map +1 -0
  147. package/dist/chunk-PNVDQL5Y.cjs +15 -0
  148. package/dist/chunk-PNVDQL5Y.cjs.map +1 -0
  149. package/dist/chunk-POQT2OIF.js +214 -0
  150. package/dist/chunk-POQT2OIF.js.map +1 -0
  151. package/dist/chunk-PSJN532Q.js +10573 -0
  152. package/dist/chunk-PSJN532Q.js.map +1 -0
  153. package/dist/chunk-QUTUJ6P6.cjs +76 -0
  154. package/dist/chunk-QUTUJ6P6.cjs.map +1 -0
  155. package/dist/chunk-R43CNCES.cjs +460 -0
  156. package/dist/chunk-R43CNCES.cjs.map +1 -0
  157. package/dist/chunk-S2BBRVQX.js +68 -0
  158. package/dist/chunk-S2BBRVQX.js.map +1 -0
  159. package/dist/chunk-S5RCBTSF.js +145 -0
  160. package/dist/chunk-S5RCBTSF.js.map +1 -0
  161. package/dist/chunk-S7OEXQMI.cjs +136 -0
  162. package/dist/chunk-S7OEXQMI.cjs.map +1 -0
  163. package/dist/chunk-SKWVAQAY.js +129 -0
  164. package/dist/chunk-SKWVAQAY.js.map +1 -0
  165. package/dist/chunk-SQLZ7ONU.js +152 -0
  166. package/dist/chunk-SQLZ7ONU.js.map +1 -0
  167. package/dist/chunk-TIZ4TS5V.cjs +72 -0
  168. package/dist/chunk-TIZ4TS5V.cjs.map +1 -0
  169. package/dist/chunk-TQKCU7CL.js +142 -0
  170. package/dist/chunk-TQKCU7CL.js.map +1 -0
  171. package/dist/chunk-U54XCYG3.js +116 -0
  172. package/dist/chunk-U54XCYG3.js.map +1 -0
  173. package/dist/chunk-U6QGZHPN.js +29 -0
  174. package/dist/chunk-U6QGZHPN.js.map +1 -0
  175. package/dist/chunk-UCFONJBG.js +79 -0
  176. package/dist/chunk-UCFONJBG.js.map +1 -0
  177. package/dist/chunk-UJ7IQJAG.js +141 -0
  178. package/dist/chunk-UJ7IQJAG.js.map +1 -0
  179. package/dist/chunk-UVNG67DG.js +253 -0
  180. package/dist/chunk-UVNG67DG.js.map +1 -0
  181. package/dist/chunk-V4XRLPEF.js +25 -0
  182. package/dist/chunk-V4XRLPEF.js.map +1 -0
  183. package/dist/chunk-VJ26EKGJ.cjs +28 -0
  184. package/dist/chunk-VJ26EKGJ.cjs.map +1 -0
  185. package/dist/chunk-VK7MAV65.cjs +90 -0
  186. package/dist/chunk-VK7MAV65.cjs.map +1 -0
  187. package/dist/chunk-VYCKUKPA.cjs +106 -0
  188. package/dist/chunk-VYCKUKPA.cjs.map +1 -0
  189. package/dist/chunk-VYHJZVL5.cjs +29 -0
  190. package/dist/chunk-VYHJZVL5.cjs.map +1 -0
  191. package/dist/chunk-WA3FO4R7.js +155 -0
  192. package/dist/chunk-WA3FO4R7.js.map +1 -0
  193. package/dist/chunk-WJVHMTKB.cjs +12 -0
  194. package/dist/chunk-WJVHMTKB.cjs.map +1 -0
  195. package/dist/chunk-WLKFWQSJ.js +333 -0
  196. package/dist/chunk-WLKFWQSJ.js.map +1 -0
  197. package/dist/chunk-WPZTYOUX.cjs +59 -0
  198. package/dist/chunk-WPZTYOUX.cjs.map +1 -0
  199. package/dist/chunk-X2FR4OIT.js +27 -0
  200. package/dist/chunk-X2FR4OIT.js.map +1 -0
  201. package/dist/chunk-XIG2IE3L.js +134 -0
  202. package/dist/chunk-XIG2IE3L.js.map +1 -0
  203. package/dist/chunk-YLQQX5W2.cjs +20 -0
  204. package/dist/chunk-YLQQX5W2.cjs.map +1 -0
  205. package/dist/chunk-YPEPCZHF.cjs +147 -0
  206. package/dist/chunk-YPEPCZHF.cjs.map +1 -0
  207. package/dist/chunk-YPQF26X7.cjs +8 -0
  208. package/dist/chunk-YPQF26X7.cjs.map +1 -0
  209. package/dist/chunk-YU6KON2I.cjs +160 -0
  210. package/dist/chunk-YU6KON2I.cjs.map +1 -0
  211. package/dist/chunk-Z2OC3UIW.cjs +388 -0
  212. package/dist/chunk-Z2OC3UIW.cjs.map +1 -0
  213. package/dist/chunk-ZUBIEQJF.cjs +10590 -0
  214. package/dist/chunk-ZUBIEQJF.cjs.map +1 -0
  215. package/dist/chunk-ZZWTY3RX.js +230 -0
  216. package/dist/chunk-ZZWTY3RX.js.map +1 -0
  217. package/dist/compact-session-OO2GD76G.js +17 -0
  218. package/dist/compact-session-OO2GD76G.js.map +1 -0
  219. package/dist/compact-session-OO7NVWPB.cjs +54 -0
  220. package/dist/compact-session-OO7NVWPB.cjs.map +1 -0
  221. package/dist/compaction.cjs +54 -303
  222. package/dist/compaction.cjs.map +1 -1
  223. package/dist/compaction.js +3 -292
  224. package/dist/compaction.js.map +1 -1
  225. package/dist/concurrency.cjs +9 -81
  226. package/dist/concurrency.cjs.map +1 -1
  227. package/dist/concurrency.js +5 -80
  228. package/dist/concurrency.js.map +1 -1
  229. package/dist/context-GWANQLX4.js +5 -0
  230. package/dist/context-GWANQLX4.js.map +1 -0
  231. package/dist/context-KNWVTZSY.cjs +22 -0
  232. package/dist/context-KNWVTZSY.cjs.map +1 -0
  233. package/dist/{cron-x3muPNgg.d.cts → cron-D0JKR-yX.d.cts} +2 -1
  234. package/dist/{cron-B_NkE_VM.d.ts → cron-DivRaEmN.d.ts} +2 -1
  235. package/dist/cron.cjs +44 -20676
  236. package/dist/cron.cjs.map +1 -1
  237. package/dist/cron.d.cts +1 -1
  238. package/dist/cron.d.ts +1 -1
  239. package/dist/cron.js +38 -20676
  240. package/dist/cron.js.map +1 -1
  241. package/dist/errors.cjs +78 -470
  242. package/dist/errors.cjs.map +1 -1
  243. package/dist/errors.d.ts +3 -424
  244. package/dist/errors.js +2 -455
  245. package/dist/errors.js.map +1 -1
  246. package/dist/eval.cjs +72 -20411
  247. package/dist/eval.cjs.map +1 -1
  248. package/dist/eval.js +59 -20402
  249. package/dist/eval.js.map +1 -1
  250. package/dist/executor-ORJS5GV2.js +981 -0
  251. package/dist/executor-ORJS5GV2.js.map +1 -0
  252. package/dist/executor-Y4MKPIUD.cjs +985 -0
  253. package/dist/executor-Y4MKPIUD.cjs.map +1 -0
  254. package/dist/filesystem/index.cjs +7 -112
  255. package/dist/filesystem/index.cjs.map +1 -1
  256. package/dist/filesystem/index.js +4 -109
  257. package/dist/filesystem/index.js.map +1 -1
  258. package/dist/fork-agent-RSV4E3EA.js +61 -0
  259. package/dist/fork-agent-RSV4E3EA.js.map +1 -0
  260. package/dist/fork-agent-Y2IK2RYU.cjs +64 -0
  261. package/dist/fork-agent-Y2IK2RYU.cjs.map +1 -0
  262. package/dist/fs-session-store-KAUQYSGI.cjs +17 -0
  263. package/dist/fs-session-store-KAUQYSGI.cjs.map +1 -0
  264. package/dist/fs-session-store-ZKB5NN37.js +8 -0
  265. package/dist/fs-session-store-ZKB5NN37.js.map +1 -0
  266. package/dist/generate-object-H3RNAM6S.cjs +20 -0
  267. package/dist/generate-object-H3RNAM6S.cjs.map +1 -0
  268. package/dist/generate-object-YJPDV5BS.js +7 -0
  269. package/dist/generate-object-YJPDV5BS.js.map +1 -0
  270. package/dist/index-manager-CB6I7XFQ.cjs +19 -0
  271. package/dist/index-manager-CB6I7XFQ.cjs.map +1 -0
  272. package/dist/index-manager-L27Q3QAC.js +10 -0
  273. package/dist/index-manager-L27Q3QAC.js.map +1 -0
  274. package/dist/index.cjs +371 -22888
  275. package/dist/index.cjs.map +1 -1
  276. package/dist/index.d.cts +16 -21
  277. package/dist/index.d.ts +16 -21
  278. package/dist/index.js +92 -22713
  279. package/dist/index.js.map +1 -1
  280. package/dist/inject-session-6MJUSGZP.cjs +27 -0
  281. package/dist/inject-session-6MJUSGZP.cjs.map +1 -0
  282. package/dist/inject-session-KOFHS5K3.js +25 -0
  283. package/dist/inject-session-KOFHS5K3.js.map +1 -0
  284. package/dist/internal/judge/judge-call.d.ts +32 -19
  285. package/dist/internal/persistence/index.cjs +93 -508
  286. package/dist/internal/persistence/index.cjs.map +1 -1
  287. package/dist/internal/persistence/index.js +11 -489
  288. package/dist/internal/persistence/index.js.map +1 -1
  289. package/dist/internal/security/index.cjs +44 -361
  290. package/dist/internal/security/index.cjs.map +1 -1
  291. package/dist/internal/security/index.js +4 -355
  292. package/dist/internal/security/index.js.map +1 -1
  293. package/dist/judge-call-CEQ3FYYD.js +126 -0
  294. package/dist/judge-call-CEQ3FYYD.js.map +1 -0
  295. package/dist/judge-call-QG4WZ7F3.cjs +130 -0
  296. package/dist/judge-call-QG4WZ7F3.cjs.map +1 -0
  297. package/dist/models.cjs +24 -919
  298. package/dist/models.cjs.map +1 -1
  299. package/dist/models.js +11 -907
  300. package/dist/models.js.map +1 -1
  301. package/dist/oauth-transaction-store-7CKHPQRN.cjs +32 -0
  302. package/dist/oauth-transaction-store-7CKHPQRN.cjs.map +1 -0
  303. package/dist/oauth-transaction-store-W74I6EFD.js +3 -0
  304. package/dist/oauth-transaction-store-W74I6EFD.js.map +1 -0
  305. package/dist/path-safety.cjs +31 -200
  306. package/dist/path-safety.cjs.map +1 -1
  307. package/dist/path-safety.js +3 -197
  308. package/dist/path-safety.js.map +1 -1
  309. package/dist/persistence.cjs +73 -393
  310. package/dist/persistence.cjs.map +1 -1
  311. package/dist/persistence.js +9 -381
  312. package/dist/persistence.js.map +1 -1
  313. package/dist/project.cjs +8 -112
  314. package/dist/project.cjs.map +1 -1
  315. package/dist/project.js +6 -110
  316. package/dist/project.js.map +1 -1
  317. package/dist/registry-34IWWDQQ.js +9 -0
  318. package/dist/registry-34IWWDQQ.js.map +1 -0
  319. package/dist/registry-APYDISL6.cjs +46 -0
  320. package/dist/registry-APYDISL6.cjs.map +1 -0
  321. package/dist/retry.cjs +7 -87
  322. package/dist/retry.cjs.map +1 -1
  323. package/dist/retry.js +3 -90
  324. package/dist/retry.js.map +1 -1
  325. package/dist/run-to-completion-J73I6IY4.cjs +48 -0
  326. package/dist/run-to-completion-J73I6IY4.cjs.map +1 -0
  327. package/dist/run-to-completion-JDPIUKSH.js +3 -0
  328. package/dist/run-to-completion-JDPIUKSH.js.map +1 -0
  329. package/dist/run-until-PNO3QQLI.cjs +180 -0
  330. package/dist/run-until-PNO3QQLI.cjs.map +1 -0
  331. package/dist/run-until-XLHEHRQM.js +177 -0
  332. package/dist/run-until-XLHEHRQM.js.map +1 -0
  333. package/dist/sandbox/index.cjs +35 -337
  334. package/dist/sandbox/index.cjs.map +1 -1
  335. package/dist/sandbox/index.js +7 -323
  336. package/dist/sandbox/index.js.map +1 -1
  337. package/dist/sanitize/index.cjs +5 -112
  338. package/dist/sanitize/index.cjs.map +1 -1
  339. package/dist/sanitize/index.js +1 -114
  340. package/dist/sanitize/index.js.map +1 -1
  341. package/dist/server/auth/index.cjs +35 -175
  342. package/dist/server/auth/index.cjs.map +1 -1
  343. package/dist/server/auth/index.js +7 -161
  344. package/dist/server/auth/index.js.map +1 -1
  345. package/dist/server/errors-envelope.cjs +17 -328
  346. package/dist/server/errors-envelope.cjs.map +1 -1
  347. package/dist/server/errors-envelope.js +4 -317
  348. package/dist/server/errors-envelope.js.map +1 -1
  349. package/dist/session-transcript-LPNZR3YS.cjs +46 -0
  350. package/dist/session-transcript-LPNZR3YS.cjs.map +1 -0
  351. package/dist/session-transcript-T7LGJUGW.js +5 -0
  352. package/dist/session-transcript-T7LGJUGW.js.map +1 -0
  353. package/dist/skills.cjs +12 -280
  354. package/dist/skills.cjs.map +1 -1
  355. package/dist/skills.js +4 -282
  356. package/dist/skills.js.map +1 -1
  357. package/dist/stream-object-QEQJJDTI.cjs +20 -0
  358. package/dist/stream-object-QEQJJDTI.cjs.map +1 -0
  359. package/dist/stream-object-WUQSSRY2.js +7 -0
  360. package/dist/stream-object-WUQSSRY2.js.map +1 -0
  361. package/dist/stream-to-completion-DFJ5T3BK.js +30 -0
  362. package/dist/stream-to-completion-DFJ5T3BK.js.map +1 -0
  363. package/dist/stream-to-completion-H2MHISSK.cjs +32 -0
  364. package/dist/stream-to-completion-H2MHISSK.cjs.map +1 -0
  365. package/dist/subagents.cjs +2 -8
  366. package/dist/subagents.cjs.map +1 -1
  367. package/dist/subagents.js +1 -7
  368. package/dist/subagents.js.map +1 -1
  369. package/dist/subscription/index.cjs +4 -17
  370. package/dist/subscription/index.cjs.map +1 -1
  371. package/dist/subscription/index.js +3 -16
  372. package/dist/subscription/index.js.map +1 -1
  373. package/dist/task-store.cjs +16 -258
  374. package/dist/task-store.cjs.map +1 -1
  375. package/dist/task-store.js +4 -259
  376. package/dist/task-store.js.map +1 -1
  377. package/dist/types/goal-events.d.ts +2 -1
  378. package/dist/workflow.cjs +71 -2797
  379. package/dist/workflow.cjs.map +1 -1
  380. package/dist/workflow.js +8 -2812
  381. package/dist/workflow.js.map +1 -1
  382. package/package.json +1 -1
@@ -0,0 +1,2863 @@
1
+ 'use strict';
2
+
3
+ var chunkLUSXDZPV_cjs = require('./chunk-LUSXDZPV.cjs');
4
+ var chunkIT3PWBW4_cjs = require('./chunk-IT3PWBW4.cjs');
5
+ var chunk6JSIEDKL_cjs = require('./chunk-6JSIEDKL.cjs');
6
+ var chunk4SXHEZIV_cjs = require('./chunk-4SXHEZIV.cjs');
7
+ var chunkEVADEGM7_cjs = require('./chunk-EVADEGM7.cjs');
8
+ var chunkD42XHI4O_cjs = require('./chunk-D42XHI4O.cjs');
9
+ var chunkA44COQJJ_cjs = require('./chunk-A44COQJJ.cjs');
10
+ var chunkBEURCLDV_cjs = require('./chunk-BEURCLDV.cjs');
11
+ var fs = require('fs');
12
+ var promises = require('fs/promises');
13
+ var os = require('os');
14
+ var path = require('path');
15
+ var url = require('url');
16
+ var module$1 = require('module');
17
+
18
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
19
+ var discoveryState = chunkD42XHI4O_cjs.globalSingleton("theokit-sdk.providers.discovered", () => ({
20
+ done: false
21
+ }));
22
+ function pluginsRoot() {
23
+ return path.join(os.homedir(), ".theokit", "plugins", "model-providers");
24
+ }
25
+ function trustFilePath() {
26
+ return path.join(os.homedir(), ".theokit", "plugins", "trusted-providers.json");
27
+ }
28
+ function loadTrustedNames() {
29
+ const trusted = /* @__PURE__ */ new Set();
30
+ const path = trustFilePath();
31
+ if (fs.existsSync(path)) {
32
+ try {
33
+ const parsed = JSON.parse(fs.readFileSync(path, "utf-8"));
34
+ if (Array.isArray(parsed)) {
35
+ let discarded = 0;
36
+ for (const name of parsed) {
37
+ if (typeof name === "string" && name.length > 0) trusted.add(name);
38
+ else discarded += 1;
39
+ }
40
+ if (discarded > 0) {
41
+ process.stderr.write(
42
+ `[theokit-sdk] WARN: ${path} contains ${discarded} non-string entr${discarded === 1 ? "y" : "ies"} \u2014 discarded (entries must be plugin-name strings)
43
+ `
44
+ );
45
+ }
46
+ } else {
47
+ process.stderr.write(
48
+ `[theokit-sdk] WARN: ${path} is not a JSON array \u2014 trusting NO provider plugins (fail-closed)
49
+ `
50
+ );
51
+ }
52
+ } catch {
53
+ process.stderr.write(
54
+ `[theokit-sdk] WARN: ${path} is not valid JSON \u2014 trusting NO provider plugins (fail-closed)
55
+ `
56
+ );
57
+ }
58
+ }
59
+ for (const name of (process.env.THEOKIT_TRUSTED_PROVIDERS ?? "").split(",")) {
60
+ const trimmed = name.trim();
61
+ if (trimmed.length > 0) trusted.add(trimmed);
62
+ }
63
+ return trusted;
64
+ }
65
+ async function discoverProviderPlugins() {
66
+ if (discoveryState.done) return;
67
+ discoveryState.done = true;
68
+ const root = pluginsRoot();
69
+ if (!fs.existsSync(root)) return;
70
+ let entries;
71
+ try {
72
+ entries = await promises.readdir(root);
73
+ } catch {
74
+ return;
75
+ }
76
+ const trusted = loadTrustedNames();
77
+ for (const entry of entries) {
78
+ if (!trusted.has(entry)) {
79
+ process.stderr.write(
80
+ `[theokit-sdk] WARN: provider plugin "${entry}" is present but NOT trusted \u2014 skipped. To trust it, add "${entry}" to ${trustFilePath()} (JSON array of names) or THEOKIT_TRUSTED_PROVIDERS (comma-separated), then restart the process.
81
+ `
82
+ );
83
+ continue;
84
+ }
85
+ await loadOne(path.join(root, entry), entry);
86
+ }
87
+ }
88
+ async function loadOne(dir, entryName) {
89
+ for (const ext of ["index.mjs", "index.js"]) {
90
+ const indexPath = path.join(dir, ext);
91
+ if (!fs.existsSync(indexPath)) continue;
92
+ try {
93
+ const mod = await import(url.pathToFileURL(indexPath).href);
94
+ const plugin = mod.default ?? mod[entryName] ?? mod;
95
+ if (plugin !== null && typeof plugin === "object" && plugin.kind === "model-provider") {
96
+ const profile = plugin.profile;
97
+ if (profile !== void 0 && typeof profile === "object") {
98
+ chunkD42XHI4O_cjs.registerProvider(profile);
99
+ }
100
+ }
101
+ return;
102
+ } catch (err) {
103
+ const msg = err instanceof Error ? err.message : String(err);
104
+ process.stderr.write(`[theokit-sdk] failed to load provider plugin "${entryName}": ${msg}
105
+ `);
106
+ return;
107
+ }
108
+ }
109
+ }
110
+
111
+ // src/internal/error-mappers/shared.ts
112
+ var RAW_MAX_BYTES = 2048;
113
+ function parseRetryAfter(headers) {
114
+ if (headers === void 0) return void 0;
115
+ const raw = headers.get("retry-after");
116
+ if (raw === null) return void 0;
117
+ const n = Number(raw);
118
+ if (Number.isFinite(n) && n >= 0) return Math.ceil(n);
119
+ const dateMs = Date.parse(raw);
120
+ if (Number.isFinite(dateMs)) return Math.max(0, Math.ceil((dateMs - Date.now()) / 1e3));
121
+ return void 0;
122
+ }
123
+ function truncateRaw(body) {
124
+ if (body === null || body === void 0) return void 0;
125
+ const s = typeof body === "string" ? body : JSON.stringify(body);
126
+ const truncated = s.length <= RAW_MAX_BYTES ? s : `${s.slice(0, RAW_MAX_BYTES)}\u2026`;
127
+ return chunkBEURCLDV_cjs.redactSecrets(truncated);
128
+ }
129
+ function buildErrorMetadata(args) {
130
+ const retryAfter = parseRetryAfter(args.headers);
131
+ const raw = truncateRaw(args.body);
132
+ return {
133
+ provider: args.provider,
134
+ endpoint: args.endpoint,
135
+ code: args.code,
136
+ statusCode: args.status,
137
+ ...retryAfter !== void 0 ? { retryAfter } : {},
138
+ ...raw !== void 0 ? { raw } : {}
139
+ };
140
+ }
141
+
142
+ // src/internal/error-mappers/anthropic.ts
143
+ function mapAnthropicError(args) {
144
+ const { status, body, headers, endpoint } = args;
145
+ const code = mapAnthropicStatusToCode(status, body);
146
+ const message = formatMessage(status, code);
147
+ const metadata = buildErrorMetadata({
148
+ provider: "anthropic",
149
+ endpoint,
150
+ code,
151
+ status,
152
+ headers,
153
+ body
154
+ });
155
+ if (status === 401 || status === 403) {
156
+ return new chunkA44COQJJ_cjs.AuthenticationError(message, { code: "anthropic_auth_failed", metadata });
157
+ }
158
+ if (status === 429) {
159
+ return new chunkA44COQJJ_cjs.RateLimitError(message, { code: "anthropic_rate_limit", metadata });
160
+ }
161
+ if (status === 400) {
162
+ return new chunkA44COQJJ_cjs.ConfigurationError(message, {
163
+ code: `anthropic_${code}`,
164
+ metadata
165
+ });
166
+ }
167
+ if (status === 408) {
168
+ return new chunkA44COQJJ_cjs.NetworkError(message, { code: "anthropic_timeout", metadata });
169
+ }
170
+ if (status >= 500 && status < 600) {
171
+ return new chunkA44COQJJ_cjs.NetworkError(message, { code: "anthropic_server_error", metadata });
172
+ }
173
+ return new chunkA44COQJJ_cjs.UnknownAgentError(message, { code: "anthropic_unknown", metadata });
174
+ }
175
+ function mapAnthropicStatusToCode(status, body) {
176
+ if (status === 401 || status === 403) return "auth_failed";
177
+ if (status === 429) return "rate_limit";
178
+ if (status === 408) return "timeout";
179
+ if (status === 400) {
180
+ const text = JSON.stringify(body ?? "").toLowerCase();
181
+ if (text.includes("context") && (text.includes("too long") || text.includes("too_long") || text.includes("length"))) {
182
+ return "context_too_long";
183
+ }
184
+ if (text.includes("filtered") || text.includes("content policy") || text.includes("content_policy")) {
185
+ return "content_filtered";
186
+ }
187
+ return "invalid_request";
188
+ }
189
+ if (status >= 500 && status < 600) return "server_error";
190
+ return "unknown";
191
+ }
192
+ function formatMessage(status, code) {
193
+ return `Anthropic API error: ${code} (HTTP ${status})`;
194
+ }
195
+
196
+ // src/internal/llm/finish.ts
197
+ function collapseSystemText(system) {
198
+ if (system === void 0) return "";
199
+ if (typeof system === "string") return system;
200
+ return system.map((b) => b.text).join("\n\n");
201
+ }
202
+ function parseToolArguments(buffered) {
203
+ if (buffered === void 0 || buffered.length === 0) return {};
204
+ try {
205
+ return JSON.parse(buffered);
206
+ } catch {
207
+ const repaired = chunk6JSIEDKL_cjs.tryJson(buffered, true);
208
+ if (chunk6JSIEDKL_cjs.isPlainObject(repaired)) return repaired;
209
+ return { raw: buffered };
210
+ }
211
+ }
212
+ function mapOpenAIFinish(reason) {
213
+ switch (reason) {
214
+ case "tool_calls":
215
+ return "tool_use";
216
+ case "length":
217
+ return "max_tokens";
218
+ default:
219
+ return "end_turn";
220
+ }
221
+ }
222
+ function makeLlmFinish(state) {
223
+ const finish = {
224
+ stopReason: state.stopReason,
225
+ text: state.text,
226
+ toolCalls: state.toolCalls
227
+ };
228
+ if (state.inputTokens !== void 0) finish.inputTokens = state.inputTokens;
229
+ if (state.outputTokens !== void 0) finish.outputTokens = state.outputTokens;
230
+ if (state.cacheReadTokens !== void 0) finish.cacheReadTokens = state.cacheReadTokens;
231
+ if (state.cacheWriteTokens !== void 0) finish.cacheWriteTokens = state.cacheWriteTokens;
232
+ if (state.reasoningTokens !== void 0) finish.reasoningTokens = state.reasoningTokens;
233
+ return finish;
234
+ }
235
+
236
+ // src/internal/llm/tool-result-content.ts
237
+ function toBlockToolResultContent(content) {
238
+ return content;
239
+ }
240
+ function toStringToolResultContent(content, providerName) {
241
+ if (typeof content === "string") return content;
242
+ if (content.some((block) => block.type === "image")) {
243
+ throw new chunkA44COQJJ_cjs.ConfigurationError(
244
+ `provider "${providerName}" does not support image content in tool results`
245
+ );
246
+ }
247
+ return content.filter(
248
+ (block) => block.type === "text"
249
+ ).map((block) => block.text).join("\n");
250
+ }
251
+ function renderToolResultContentText(content, fn) {
252
+ if (typeof content === "string") return fn(content);
253
+ return content.map(
254
+ (block) => block.type === "text" ? { type: "text", text: fn(block.text) } : block
255
+ );
256
+ }
257
+
258
+ // src/internal/llm/anthropic-shared.ts
259
+ function extractAnthropicText(response) {
260
+ return (response.content ?? []).filter((c) => c.type === "text").map((c) => c.text).join("");
261
+ }
262
+ function extractAnthropicToolCalls(response) {
263
+ return (response.content ?? []).filter(
264
+ (c) => c.type === "tool_use"
265
+ ).map((c) => ({
266
+ type: "tool_use",
267
+ id: c.id,
268
+ name: c.name,
269
+ input: parseToolArguments(JSON.stringify(c.input))
270
+ }));
271
+ }
272
+ function mapAnthropicStopReason(reason) {
273
+ switch (reason) {
274
+ case "tool_use":
275
+ return "tool_use";
276
+ case "max_tokens":
277
+ return "max_tokens";
278
+ case "stop_sequence":
279
+ return "stop_sequence";
280
+ case "end_turn":
281
+ case null:
282
+ return "end_turn";
283
+ default:
284
+ return "end_turn";
285
+ }
286
+ }
287
+ function toAnthropicWireMessage(message) {
288
+ const role = message.role === "system" ? "user" : message.role;
289
+ const content = message.content.map((part) => {
290
+ if (part.type === "text") return { type: "text", text: part.text };
291
+ if (part.type === "tool_use") {
292
+ return { type: "tool_use", id: part.id, name: part.name, input: part.input };
293
+ }
294
+ if (part.type === "image") {
295
+ return { type: "image", source: part.source };
296
+ }
297
+ return {
298
+ type: "tool_result",
299
+ tool_use_id: part.toolUseId,
300
+ // SE7 — this wire is block-capable: strings pass through, structured
301
+ // text/image blocks are forwarded natively.
302
+ content: toBlockToolResultContent(part.content),
303
+ ...part.isError === true ? { is_error: true } : {}
304
+ };
305
+ });
306
+ return { role, content };
307
+ }
308
+ function postAnthropicRequest(args) {
309
+ return args.fetchImpl(args.url, {
310
+ method: "POST",
311
+ signal: args.signal,
312
+ headers: {
313
+ "content-type": "application/json",
314
+ accept: "application/json",
315
+ authorization: `Bearer ${args.token}`
316
+ },
317
+ body: JSON.stringify(args.body)
318
+ });
319
+ }
320
+ async function handleAnthropicResponse(args) {
321
+ if (!args.response.ok) {
322
+ throw args.errorMapper({
323
+ status: args.response.status,
324
+ body: await parseHttpErrorBody(args.response),
325
+ headers: args.response.headers,
326
+ endpoint: args.endpoint
327
+ });
328
+ }
329
+ return consumeAnthropicResponse(args.response);
330
+ }
331
+ async function consumeAnthropicResponse(response) {
332
+ const data = await response.json();
333
+ return {
334
+ text: extractAnthropicText(data),
335
+ toolCalls: extractAnthropicToolCalls(data),
336
+ stopReason: mapAnthropicStopReason(data.stop_reason ?? null),
337
+ inputTokens: data.usage?.input_tokens,
338
+ outputTokens: data.usage?.output_tokens
339
+ };
340
+ }
341
+ async function parseHttpErrorBody(response) {
342
+ const text = await response.text().catch(() => "");
343
+ try {
344
+ return JSON.parse(text);
345
+ } catch {
346
+ return text;
347
+ }
348
+ }
349
+ function buildAnthropicCommonBody(request) {
350
+ const body = {
351
+ max_tokens: request.maxTokens ?? 4096,
352
+ messages: request.messages.map(toAnthropicWireMessage)
353
+ };
354
+ const wireSystem = encodeAnthropicSystem(request.system);
355
+ if (wireSystem !== void 0) body.system = wireSystem;
356
+ if (request.temperature !== void 0) body.temperature = request.temperature;
357
+ if (request.tools !== void 0 && request.tools.length > 0) {
358
+ body.tools = request.tools.map((tool) => ({
359
+ name: tool.name,
360
+ description: tool.description,
361
+ input_schema: tool.inputSchema
362
+ }));
363
+ }
364
+ return body;
365
+ }
366
+ function encodeAnthropicSystem(system) {
367
+ if (system === void 0) return void 0;
368
+ if (typeof system === "string") return system;
369
+ if (system.length === 0) return void 0;
370
+ return system.map((block) => {
371
+ const wire = { type: "text", text: block.text };
372
+ if (block.cacheable === true) wire.cache_control = { type: "ephemeral" };
373
+ return wire;
374
+ });
375
+ }
376
+
377
+ // src/internal/llm/sse.ts
378
+ var DEFAULT_SSE_IDLE_MS = 6e4;
379
+ async function* parseSseStream(body, signal, idleTimeoutMs = DEFAULT_SSE_IDLE_MS) {
380
+ if (body === null) return;
381
+ const reader = body.getReader();
382
+ const decoder = new TextDecoder("utf-8");
383
+ const state = { buffer: "", event: "message", data: "" };
384
+ try {
385
+ for await (const chunk of readChunks(reader, signal, idleTimeoutMs)) {
386
+ state.buffer += decoder.decode(chunk, { stream: true });
387
+ for (const record of drainCompleteRecords(state)) yield record;
388
+ }
389
+ if (state.data.length > 0) yield { event: state.event, data: state.data };
390
+ } finally {
391
+ await cancelReaderQuietly(reader);
392
+ releaseReader(reader);
393
+ }
394
+ }
395
+ async function* readChunks(reader, signal, idleTimeoutMs) {
396
+ while (true) {
397
+ if (signal.aborted) return;
398
+ const { value, done } = await readWithIdleTimeout(reader, idleTimeoutMs);
399
+ if (done) return;
400
+ if (value !== void 0) yield value;
401
+ }
402
+ }
403
+ function readWithIdleTimeout(reader, idleTimeoutMs) {
404
+ if (idleTimeoutMs <= 0) return reader.read();
405
+ return new Promise(
406
+ (resolve, reject) => {
407
+ const timer = setTimeout(() => {
408
+ reject(
409
+ new chunkA44COQJJ_cjs.NetworkError(`SSE stream idle for ${idleTimeoutMs}ms \u2014 upstream stalled`, {
410
+ code: "stream_idle_timeout"
411
+ })
412
+ );
413
+ }, idleTimeoutMs);
414
+ reader.read().then(
415
+ (result) => {
416
+ clearTimeout(timer);
417
+ resolve(result);
418
+ },
419
+ (err) => {
420
+ clearTimeout(timer);
421
+ reject(err);
422
+ }
423
+ );
424
+ }
425
+ );
426
+ }
427
+ async function cancelReaderQuietly(reader) {
428
+ try {
429
+ await reader.cancel();
430
+ } catch {
431
+ }
432
+ }
433
+ function drainCompleteRecords(state) {
434
+ const out = [];
435
+ let newlineIndex = state.buffer.indexOf("\n");
436
+ while (newlineIndex !== -1) {
437
+ const line = state.buffer.slice(0, newlineIndex).replace(/\r$/, "");
438
+ state.buffer = state.buffer.slice(newlineIndex + 1);
439
+ const finished = applyLine(state, line);
440
+ if (finished !== void 0) out.push(finished);
441
+ newlineIndex = state.buffer.indexOf("\n");
442
+ }
443
+ return out;
444
+ }
445
+ function applyLine(state, line) {
446
+ if (line === "") {
447
+ if (state.data.length === 0) {
448
+ state.event = "message";
449
+ return void 0;
450
+ }
451
+ const record = { event: state.event, data: state.data };
452
+ state.event = "message";
453
+ state.data = "";
454
+ return record;
455
+ }
456
+ if (line.startsWith(":")) return void 0;
457
+ if (line.startsWith("event:")) {
458
+ state.event = stripOneLeadingSpace(line.slice(6));
459
+ return void 0;
460
+ }
461
+ if (line.startsWith("data:")) {
462
+ const piece = stripOneLeadingSpace(line.slice(5));
463
+ state.data = state.data.length === 0 ? piece : `${state.data}
464
+ ${piece}`;
465
+ }
466
+ return void 0;
467
+ }
468
+ function stripOneLeadingSpace(value) {
469
+ return value.startsWith(" ") ? value.slice(1) : value;
470
+ }
471
+ function releaseReader(reader) {
472
+ try {
473
+ reader.releaseLock();
474
+ } catch {
475
+ }
476
+ }
477
+
478
+ // src/internal/llm/anthropic.ts
479
+ var AnthropicClient = class {
480
+ constructor(options) {
481
+ this.options = options;
482
+ this.baseUrl = options.baseUrl ?? "https://api.anthropic.com";
483
+ this.fetchImpl = options.fetch ?? fetch;
484
+ }
485
+ options;
486
+ name = "anthropic";
487
+ baseUrl;
488
+ fetchImpl;
489
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: HTTP+SSE handshake + accumulator is intentionally one block
490
+ async *stream(request, signal) {
491
+ const body = buildAnthropicBody(request);
492
+ const headers = {
493
+ "content-type": "application/json",
494
+ "x-api-key": this.options.apiKey,
495
+ "anthropic-version": this.options.version ?? "2023-06-01"
496
+ };
497
+ if (this.options.extraHeaders !== void 0) Object.assign(headers, this.options.extraHeaders);
498
+ const response = await this.fetchImpl(`${this.baseUrl}/v1/messages`, {
499
+ method: "POST",
500
+ signal,
501
+ headers,
502
+ body: JSON.stringify(body)
503
+ });
504
+ if (!response.ok) {
505
+ const text = await response.text().catch(() => "");
506
+ let body2 = text;
507
+ try {
508
+ body2 = JSON.parse(text);
509
+ } catch {
510
+ }
511
+ throw mapAnthropicError({
512
+ status: response.status,
513
+ body: body2,
514
+ headers: response.headers,
515
+ endpoint: "/v1/messages"
516
+ });
517
+ }
518
+ const accumulator = new AnthropicStreamAccumulator();
519
+ for await (const record of parseSseStream(response.body, signal)) {
520
+ if (record.event === "ping" || record.event === "message_start") continue;
521
+ let parsed;
522
+ try {
523
+ parsed = JSON.parse(record.data);
524
+ } catch {
525
+ continue;
526
+ }
527
+ const events = accumulator.consume(parsed);
528
+ for (const event of events) yield event;
529
+ }
530
+ if (!accumulator.finishReasonSeen) {
531
+ throw new chunkA44COQJJ_cjs.NetworkError("Anthropic SSE stream truncated (no stop_reason)", {
532
+ code: "stream_truncated"
533
+ });
534
+ }
535
+ return accumulator.finish();
536
+ }
537
+ };
538
+ var AnthropicStreamAccumulator = class {
539
+ text = "";
540
+ stopReason = "end_turn";
541
+ /**
542
+ * M2 #61 — whether a `message_delta` carrying a real `stop_reason` was seen.
543
+ * A stream that closes before it is a truncation (server FIN / proxy hiccup),
544
+ * not a clean `end_turn` — the caller throws `stream_truncated` on `false`.
545
+ */
546
+ sawStopReason = false;
547
+ inputTokens;
548
+ outputTokens;
549
+ cacheReadTokens;
550
+ cacheWriteTokens;
551
+ toolCalls = /* @__PURE__ */ new Map();
552
+ toolBuffers = /* @__PURE__ */ new Map();
553
+ consume(event) {
554
+ if (event.type === "content_block_start") {
555
+ this.handleToolStart(event);
556
+ return [];
557
+ }
558
+ if (event.type === "content_block_delta") {
559
+ return this.handleContentDelta(event);
560
+ }
561
+ if (event.type === "message_delta") {
562
+ this.handleMessageDelta(event);
563
+ }
564
+ return [];
565
+ }
566
+ handleToolStart(start) {
567
+ if (start.content_block.type !== "tool_use") return;
568
+ this.toolCalls.set(start.index, {
569
+ type: "tool_use",
570
+ id: start.content_block.id,
571
+ name: start.content_block.name,
572
+ input: { ...start.content_block.input }
573
+ });
574
+ this.toolBuffers.set(start.index, "");
575
+ }
576
+ handleContentDelta(delta) {
577
+ if (delta.delta.type === "text_delta") {
578
+ const text = delta.delta.text;
579
+ this.text += text;
580
+ return [{ type: "text_delta", text }];
581
+ }
582
+ const idx = delta.index;
583
+ const existing = this.toolBuffers.get(idx) ?? "";
584
+ this.toolBuffers.set(idx, existing + delta.delta.partial_json);
585
+ return [];
586
+ }
587
+ /**
588
+ * T3.8 — extract token counters from Anthropic's `message_delta` usage.
589
+ * Public on the class so the test seam can drive it directly without
590
+ * spinning the SSE parser.
591
+ */
592
+ handleMessageDelta(md) {
593
+ if (md.delta.stop_reason !== void 0 && md.delta.stop_reason !== null) {
594
+ this.sawStopReason = true;
595
+ }
596
+ this.stopReason = mapAnthropicStopReason(md.delta.stop_reason);
597
+ if (md.usage?.input_tokens !== void 0) this.inputTokens = md.usage.input_tokens;
598
+ if (md.usage?.output_tokens !== void 0) this.outputTokens = md.usage.output_tokens;
599
+ if (md.usage?.cache_creation_input_tokens !== void 0 && md.usage.cache_creation_input_tokens > 0) {
600
+ this.cacheWriteTokens = md.usage.cache_creation_input_tokens;
601
+ }
602
+ if (md.usage?.cache_read_input_tokens !== void 0 && md.usage.cache_read_input_tokens > 0) {
603
+ this.cacheReadTokens = md.usage.cache_read_input_tokens;
604
+ }
605
+ }
606
+ /** M2 #61 — whether the terminal `message_delta` (stop_reason) was seen. */
607
+ get finishReasonSeen() {
608
+ return this.sawStopReason;
609
+ }
610
+ finish() {
611
+ const toolCalls = [];
612
+ for (const [index, tool] of this.toolCalls.entries()) {
613
+ const buffered = this.toolBuffers.get(index);
614
+ const parsed = parseToolArguments(buffered);
615
+ if (Object.keys(parsed).length > 0) tool.input = parsed;
616
+ toolCalls.push(tool);
617
+ }
618
+ return makeLlmFinish({
619
+ stopReason: this.stopReason,
620
+ text: this.text,
621
+ toolCalls,
622
+ inputTokens: this.inputTokens,
623
+ outputTokens: this.outputTokens,
624
+ // T3.8 — surface Anthropic native cache-token counters when the
625
+ // request used `cache_control: {type:"ephemeral"}` on system blocks.
626
+ cacheReadTokens: this.cacheReadTokens,
627
+ cacheWriteTokens: this.cacheWriteTokens
628
+ });
629
+ }
630
+ };
631
+ function buildAnthropicBody(request) {
632
+ return {
633
+ model: request.model,
634
+ stream: true,
635
+ ...buildAnthropicCommonBody(request)
636
+ };
637
+ }
638
+
639
+ // src/internal/error-mappers/bedrock.ts
640
+ function classifyBedrockError(args, awsType, message) {
641
+ if (args.status === 429 || awsType.includes("Throttling") || awsType.includes("TooManyRequests")) {
642
+ return "rate_limit";
643
+ }
644
+ if (args.status === 401 || args.status === 403 || awsType.includes("AccessDenied") || awsType.includes("UnauthorizedOperation")) {
645
+ return "auth_failed";
646
+ }
647
+ if (args.status === 400 || args.status === 404 || awsType.includes("ValidationException") || awsType.includes("ResourceNotFound") || message.includes("use case details")) {
648
+ return "invalid_request";
649
+ }
650
+ if (args.status === 408 || awsType.includes("Timeout")) return "timeout";
651
+ if (args.status >= 500) return "server_error";
652
+ return "unknown";
653
+ }
654
+ function buildBedrockMetadata(args, code) {
655
+ return buildErrorMetadata({
656
+ provider: "bedrock",
657
+ endpoint: args.endpoint,
658
+ code,
659
+ status: args.status,
660
+ headers: args.headers,
661
+ body: args.body
662
+ });
663
+ }
664
+ function mapBedrockError(args) {
665
+ const parsed = parseBody(args.body);
666
+ const awsType = parsed.__type ?? "";
667
+ const message = parsed.message ?? parsed.Message ?? "Bedrock request failed";
668
+ const code = classifyBedrockError(args, awsType, message);
669
+ const metadata = buildBedrockMetadata(args, code);
670
+ switch (code) {
671
+ case "rate_limit":
672
+ return new chunkA44COQJJ_cjs.RateLimitError(`Bedrock throttled: ${message}`, { metadata });
673
+ case "auth_failed":
674
+ return new chunkA44COQJJ_cjs.AuthenticationError(`Bedrock auth: ${message}`, { metadata });
675
+ case "invalid_request": {
676
+ const friendly = message.includes("use case details") ? `Bedrock account setup required: ${message} (AWS Console \u2192 Bedrock \u2192 Model access \u2192 Anthropic \u2192 Submit use case form, then retry in 15 min.)` : `Bedrock validation: ${message}`;
677
+ return new chunkA44COQJJ_cjs.ConfigurationError(friendly, { metadata });
678
+ }
679
+ case "timeout":
680
+ return new chunkA44COQJJ_cjs.NetworkError(`Bedrock timeout: ${message}`, { metadata });
681
+ case "server_error":
682
+ return new chunkA44COQJJ_cjs.NetworkError(`Bedrock server error: ${message}`, { metadata });
683
+ default:
684
+ return new chunkA44COQJJ_cjs.UnknownAgentError(`Bedrock unknown: ${message}`, { metadata });
685
+ }
686
+ }
687
+ function parseBody(body) {
688
+ if (body !== null && typeof body === "object") return body;
689
+ if (typeof body === "string") {
690
+ try {
691
+ return JSON.parse(body);
692
+ } catch {
693
+ return {};
694
+ }
695
+ }
696
+ return {};
697
+ }
698
+ var cachedToken = null;
699
+ var CACHE_TTL_MS = 90 * 60 * 1e3;
700
+ async function resolveBedrockToken(region) {
701
+ const env = process.env.AWS_BEARER_TOKEN_BEDROCK;
702
+ if (env !== void 0 && env.length > 0) return env;
703
+ const now = Date.now();
704
+ if (cachedToken !== null && cachedToken.expiresAt > now) {
705
+ return cachedToken.value;
706
+ }
707
+ try {
708
+ const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-2MF3IE2D.cjs', document.baseURI).href)));
709
+ const gen = r("@aws/bedrock-token-generator");
710
+ if (typeof gen.getToken !== "function") return void 0;
711
+ const providers = r("@aws-sdk/credential-providers");
712
+ if (typeof providers.fromNodeProviderChain !== "function") return void 0;
713
+ const credentialProvider = providers.fromNodeProviderChain();
714
+ const token = await gen.getToken({ credentials: credentialProvider, region });
715
+ cachedToken = { value: token, expiresAt: now + CACHE_TTL_MS };
716
+ return token;
717
+ } catch {
718
+ return void 0;
719
+ }
720
+ }
721
+
722
+ // src/internal/llm/bedrock-anthropic.ts
723
+ var BedrockAnthropicClient = class {
724
+ constructor(options) {
725
+ this.options = options;
726
+ this.fetchImpl = options.fetch ?? fetch;
727
+ }
728
+ options;
729
+ name = "bedrock";
730
+ fetchImpl;
731
+ async resolveTokenOrThrow(region) {
732
+ const fromOpts = this.options.apiKey;
733
+ if (fromOpts !== void 0 && fromOpts.length > 0) return fromOpts;
734
+ const fromEnv = await resolveBedrockToken(region);
735
+ if (fromEnv !== void 0 && fromEnv.length > 0) return fromEnv;
736
+ throw new chunkA44COQJJ_cjs.ConfigurationError(
737
+ "Bedrock requires AWS_BEARER_TOKEN_BEDROCK env var, or install `@aws/bedrock-token-generator` for auto-refresh, or pass apiKey explicitly.",
738
+ { code: "auth_failed" }
739
+ );
740
+ }
741
+ async *stream(request, signal) {
742
+ const region = chunkD42XHI4O_cjs.inferRegionFromModelId(request.model) ?? process.env.AWS_REGION ?? "us-east-1";
743
+ const token = await this.resolveTokenOrThrow(region);
744
+ const bareModel = chunkD42XHI4O_cjs.stripBedrockPrefix(request.model);
745
+ const baseUrl = this.options.baseUrl ?? chunkD42XHI4O_cjs.resolveBedrockBaseUrl(request.model);
746
+ const endpoint = `/model/${encodeURIComponent(bareModel)}/invoke`;
747
+ const url = `${baseUrl}${endpoint}`;
748
+ const response = await postAnthropicRequest({
749
+ fetchImpl: this.fetchImpl,
750
+ url,
751
+ token,
752
+ body: buildBedrockBody(request),
753
+ signal
754
+ });
755
+ const consumed = await handleAnthropicResponse({
756
+ response,
757
+ endpoint,
758
+ errorMapper: mapBedrockError
759
+ });
760
+ if (consumed.text.length > 0) yield { type: "text_delta", text: consumed.text };
761
+ return makeLlmFinish(consumed);
762
+ }
763
+ };
764
+ function buildBedrockBody(request) {
765
+ return {
766
+ anthropic_version: "bedrock-2023-05-31",
767
+ ...buildAnthropicCommonBody(request)
768
+ };
769
+ }
770
+
771
+ // src/internal/error-mappers/openai-compatible.ts
772
+ function mapOpenAICompatibleError(args) {
773
+ const { providerId, status, body, headers, endpoint } = args;
774
+ const code = mapOpenAiStatusToCode(status, body);
775
+ const message = formatMessage2(providerId, status, code);
776
+ const metadata = buildErrorMetadata({
777
+ provider: providerId,
778
+ endpoint,
779
+ code,
780
+ status,
781
+ headers,
782
+ body
783
+ });
784
+ if (status === 401 || status === 403) {
785
+ return new chunkA44COQJJ_cjs.AuthenticationError(message, { code: `${providerId}_auth_failed`, metadata });
786
+ }
787
+ if (status === 429) {
788
+ return new chunkA44COQJJ_cjs.RateLimitError(message, { code: `${providerId}_rate_limit`, metadata });
789
+ }
790
+ if (status === 400) {
791
+ return new chunkA44COQJJ_cjs.ConfigurationError(message, { code: `${providerId}_${code}`, metadata });
792
+ }
793
+ if (status === 408) {
794
+ return new chunkA44COQJJ_cjs.NetworkError(message, { code: `${providerId}_timeout`, metadata });
795
+ }
796
+ if (status >= 500 && status < 600) {
797
+ return new chunkA44COQJJ_cjs.NetworkError(message, { code: `${providerId}_server_error`, metadata });
798
+ }
799
+ return new chunkA44COQJJ_cjs.UnknownAgentError(message, { code: `${providerId}_unknown`, metadata });
800
+ }
801
+ function extractOpenAiErrorCode(body) {
802
+ if (body === null || typeof body !== "object") return void 0;
803
+ const err = body.error;
804
+ if (err === void 0 || err === null) return void 0;
805
+ if (typeof err.code === "string") return err.code;
806
+ if (typeof err.type === "string") return err.type;
807
+ return void 0;
808
+ }
809
+ function mapOpenAiStatusToCode(status, body) {
810
+ const rawCode = extractOpenAiErrorCode(body)?.toLowerCase() ?? "";
811
+ if (rawCode.includes("context_length") || rawCode.includes("context_window") || rawCode.includes("too_many_tokens") || rawCode.includes("max_tokens")) {
812
+ return "context_too_long";
813
+ }
814
+ if (rawCode.includes("content_filter") || rawCode.includes("content_policy") || rawCode.includes("safety")) {
815
+ return "content_filtered";
816
+ }
817
+ if (rawCode.includes("model_not_found") || rawCode.includes("model_unavailable") || rawCode.includes("invalid_model")) {
818
+ return "model_unavailable";
819
+ }
820
+ if (status === 402 || rawCode.includes("insufficient_quota") || rawCode.includes("quota_exceeded")) {
821
+ return "quota_exceeded";
822
+ }
823
+ if (status === 401 || status === 403) return "auth_failed";
824
+ if (status === 429) return "rate_limit";
825
+ if (status === 408) return "timeout";
826
+ if (status === 400) return "invalid_request";
827
+ if (status >= 500 && status < 600) return "server_error";
828
+ return "unknown";
829
+ }
830
+ function formatMessage2(providerId, status, code) {
831
+ return `${providerId} API error: ${code} (HTTP ${status})`;
832
+ }
833
+
834
+ // src/internal/llm/fault-injection.ts
835
+ var ENV_GATE_KEY = "NODE_ENV";
836
+ var ENV_GATE_VALUE = "test";
837
+ var ENV_OVERRIDE_KEY = "THEOKIT_TEST_RESPONSE_OVERRIDE";
838
+ function maybeWrapWithFaultInjection(client) {
839
+ if (!isGateOn()) return client;
840
+ return new FaultInjectingLlmClient(client);
841
+ }
842
+ var FaultInjectingLlmClient = class {
843
+ name;
844
+ /**
845
+ * Inner (real) client. Exposed so layered transport assertions (router
846
+ * pool-wiring tests, telemetry inspectors) can walk one level deep —
847
+ * same pattern PoolAwareLlmClient uses for its inner transport.
848
+ */
849
+ inner;
850
+ constructor(inner) {
851
+ this.inner = inner;
852
+ this.name = inner.name;
853
+ }
854
+ async *stream(request, signal) {
855
+ if (!isGateOn()) {
856
+ return yield* this.inner.stream(request, signal);
857
+ }
858
+ const parsed = parseOverrideOrWarnOnce();
859
+ if (parsed === void 0) {
860
+ return yield* this.inner.stream(request, signal);
861
+ }
862
+ if (parsed.status >= 400) {
863
+ throw mapOpenAICompatibleError({
864
+ providerId: this.name,
865
+ status: parsed.status,
866
+ body: parsed.body,
867
+ headers: void 0,
868
+ endpoint: "/v1/chat/completions"
869
+ });
870
+ }
871
+ const text = extractText(parsed.body);
872
+ yield { type: "text_delta", text };
873
+ yield { type: "stop", reason: "end_turn" };
874
+ return {
875
+ stopReason: "end_turn",
876
+ text,
877
+ toolCalls: [],
878
+ inputTokens: 0,
879
+ outputTokens: 0
880
+ };
881
+ }
882
+ };
883
+ function isGateOn() {
884
+ return process.env[ENV_GATE_KEY] === ENV_GATE_VALUE;
885
+ }
886
+ var warnedInvalidJson = false;
887
+ function parseOverrideOrWarnOnce() {
888
+ const raw = process.env[ENV_OVERRIDE_KEY];
889
+ if (raw === void 0 || raw.length === 0) return void 0;
890
+ let candidate;
891
+ try {
892
+ candidate = JSON.parse(raw);
893
+ } catch (_err) {
894
+ warnInvalidJsonOnce();
895
+ return void 0;
896
+ }
897
+ if (candidate === null || typeof candidate !== "object") {
898
+ warnInvalidJsonOnce();
899
+ return void 0;
900
+ }
901
+ const obj = candidate;
902
+ if (typeof obj.status !== "number" || !Number.isFinite(obj.status)) {
903
+ warnInvalidJsonOnce();
904
+ return void 0;
905
+ }
906
+ return { status: obj.status, body: obj.body };
907
+ }
908
+ function warnInvalidJsonOnce(_raw) {
909
+ if (warnedInvalidJson) return;
910
+ warnedInvalidJson = true;
911
+ process.stderr.write(
912
+ `[theokit-sdk] ${ENV_OVERRIDE_KEY} is set but value is not valid JSON of shape \`{"status": number, "body": object | string}\`. Falling back to real LLM call. This warning is shown once per process.
913
+ `
914
+ );
915
+ }
916
+ function extractText(body) {
917
+ if (typeof body === "string") return body;
918
+ if (body === null || typeof body !== "object") return "";
919
+ const fromOpenAi = readOpenAiContent(body);
920
+ if (fromOpenAi !== void 0) return fromOpenAi;
921
+ const obj = body;
922
+ if (typeof obj.text === "string") return obj.text;
923
+ return "";
924
+ }
925
+ function readOpenAiContent(body) {
926
+ const obj = body;
927
+ if (!Array.isArray(obj.choices) || obj.choices.length === 0) return void 0;
928
+ const first = obj.choices[0];
929
+ const content = first?.message?.content;
930
+ if (typeof content === "string") return content;
931
+ return void 0;
932
+ }
933
+
934
+ // src/internal/error-mappers/ollama.ts
935
+ function mapOllamaTransportError(args) {
936
+ if (args.providerId !== "ollama") return void 0;
937
+ const causeCode = extractCauseCode(args.cause);
938
+ if (causeCode !== "ECONNREFUSED" && causeCode !== "ENOTFOUND") return void 0;
939
+ const metadata = buildErrorMetadata({
940
+ provider: "ollama",
941
+ endpoint: args.endpoint,
942
+ code: "network",
943
+ status: 0,
944
+ headers: void 0,
945
+ body: { cause: causeCode }
946
+ });
947
+ return new chunkA44COQJJ_cjs.ConfigurationError(
948
+ "Ollama is not reachable. Run `ollama serve` to start the local runtime, or set OLLAMA_HOST to point at a remote Ollama server.",
949
+ { code: "ollama_unreachable", metadata }
950
+ );
951
+ }
952
+ function mapOllamaHttpError(args) {
953
+ if (args.providerId !== "ollama") return void 0;
954
+ const errString = extractErrorString(args.body).toLowerCase();
955
+ if (args.status === 404 && errString.includes("not found") && errString.includes("pull")) {
956
+ const modelHint = extractModelName(errString);
957
+ const metadata = buildErrorMetadata({
958
+ provider: "ollama",
959
+ endpoint: args.endpoint,
960
+ code: "model_unavailable",
961
+ status: args.status,
962
+ headers: args.headers,
963
+ body: args.body
964
+ });
965
+ const pullCmd = modelHint !== void 0 ? `ollama pull ${modelHint}` : "ollama pull <model>";
966
+ return new chunkA44COQJJ_cjs.ConfigurationError(
967
+ `Ollama model is not pulled. Run \`${pullCmd}\` to download it first.`,
968
+ { code: "ollama_model_not_pulled", metadata }
969
+ );
970
+ }
971
+ if (args.status === 503 && errString.includes("model is loading")) {
972
+ const metadata = buildErrorMetadata({
973
+ provider: "ollama",
974
+ endpoint: args.endpoint,
975
+ code: "server_error",
976
+ status: args.status,
977
+ headers: args.headers,
978
+ body: args.body
979
+ });
980
+ return new chunkA44COQJJ_cjs.NetworkError(
981
+ "Ollama model is loading. Retry in a few seconds \u2014 Ollama is warming up the model into memory.",
982
+ { code: "ollama_model_loading", metadata }
983
+ );
984
+ }
985
+ return void 0;
986
+ }
987
+ function extractCauseCode(cause) {
988
+ if (cause === null || typeof cause !== "object") return void 0;
989
+ const directCode = cause.code;
990
+ if (typeof directCode === "string") return directCode;
991
+ const nested = cause.cause;
992
+ if (nested !== void 0) return extractCauseCode(nested);
993
+ return void 0;
994
+ }
995
+ function extractErrorString(body) {
996
+ if (typeof body === "string") return body;
997
+ if (body === null || typeof body !== "object") return "";
998
+ const err = body.error;
999
+ if (typeof err === "string") return err;
1000
+ return "";
1001
+ }
1002
+ function extractModelName(errString) {
1003
+ const match = errString.match(/'([^']+)'/);
1004
+ return match?.[1];
1005
+ }
1006
+
1007
+ // src/internal/llm/ollama-native.ts
1008
+ var OllamaNativeClient = class {
1009
+ constructor(options) {
1010
+ this.options = options;
1011
+ const raw = (options.baseUrl ?? "http://localhost:11434").replace(/\/+$/, "");
1012
+ this.baseUrl = raw.replace(/\/v1$/i, "");
1013
+ this.fetchImpl = options.fetch ?? fetch;
1014
+ }
1015
+ options;
1016
+ name = "ollama";
1017
+ baseUrl;
1018
+ fetchImpl;
1019
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: HTTP+NDJSON handshake + accumulator is intentionally one block (mirrors openai.ts)
1020
+ async *stream(request, signal) {
1021
+ const headers = { "content-type": "application/json" };
1022
+ if (this.options.apiKey !== void 0 && this.options.apiKey.length > 0) {
1023
+ headers.authorization = `Bearer ${this.options.apiKey}`;
1024
+ }
1025
+ const body = buildOllamaChatBody(request);
1026
+ const url = `${this.baseUrl}/api/chat`;
1027
+ let response;
1028
+ try {
1029
+ response = await this.fetchImpl(url, {
1030
+ method: "POST",
1031
+ signal,
1032
+ headers,
1033
+ body: JSON.stringify(body)
1034
+ });
1035
+ } catch (fetchErr) {
1036
+ const mapped = mapOllamaTransportError({
1037
+ providerId: "ollama",
1038
+ cause: fetchErr,
1039
+ endpoint: "/api/chat"
1040
+ });
1041
+ if (mapped !== void 0) throw mapped;
1042
+ throw fetchErr;
1043
+ }
1044
+ if (!response.ok) {
1045
+ const text = await response.text().catch(() => "");
1046
+ let bodyJson = text;
1047
+ try {
1048
+ bodyJson = JSON.parse(text);
1049
+ } catch {
1050
+ }
1051
+ const mapped = mapOllamaHttpError({
1052
+ providerId: "ollama",
1053
+ status: response.status,
1054
+ body: bodyJson,
1055
+ headers: response.headers,
1056
+ endpoint: "/api/chat"
1057
+ });
1058
+ if (mapped !== void 0) throw mapped;
1059
+ throw new Error(`Ollama /api/chat HTTP ${response.status}: ${text.slice(0, 200)}`);
1060
+ }
1061
+ const accumulator = new OllamaStreamAccumulator();
1062
+ if (response.body === null) {
1063
+ return accumulator.finish();
1064
+ }
1065
+ for await (const chunk of parseNdjsonStream(response.body, signal)) {
1066
+ const events = accumulator.consume(chunk);
1067
+ for (const event of events) yield event;
1068
+ if (chunk.done === true) break;
1069
+ }
1070
+ return accumulator.finish();
1071
+ }
1072
+ };
1073
+ var OllamaStreamAccumulator = class {
1074
+ text = "";
1075
+ stopReason = "end_turn";
1076
+ inputTokens;
1077
+ outputTokens;
1078
+ toolCalls = [];
1079
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: NDJSON chunk dispatch — text delta + tool_call append + finish-reason mapping is one cohesive accumulator (mirrors openai.ts OpenAIStreamAccumulator.consume).
1080
+ consume(chunk) {
1081
+ const events = [];
1082
+ if (chunk.prompt_eval_count !== void 0) this.inputTokens = chunk.prompt_eval_count;
1083
+ if (chunk.eval_count !== void 0) this.outputTokens = chunk.eval_count;
1084
+ const msg = chunk.message;
1085
+ if (msg?.content !== void 0 && msg.content.length > 0) {
1086
+ this.text += msg.content;
1087
+ events.push({ type: "text_delta", text: msg.content });
1088
+ }
1089
+ if (msg?.tool_calls !== void 0) {
1090
+ for (const call of msg.tool_calls) {
1091
+ const input = typeof call.function.arguments === "string" ? parseOllamaToolArguments(call.function.arguments) : call.function.arguments;
1092
+ this.toolCalls.push({
1093
+ type: "tool_use",
1094
+ id: `ollama_call_${this.toolCalls.length + 1}`,
1095
+ name: call.function.name,
1096
+ input
1097
+ });
1098
+ }
1099
+ }
1100
+ if (chunk.done === true && chunk.done_reason !== void 0) {
1101
+ this.stopReason = mapOllamaDoneReason(chunk.done_reason, this.toolCalls.length > 0);
1102
+ }
1103
+ return events;
1104
+ }
1105
+ finish() {
1106
+ if (this.toolCalls.length > 0 && this.stopReason === "end_turn") {
1107
+ this.stopReason = "tool_use";
1108
+ }
1109
+ return makeLlmFinish({
1110
+ stopReason: this.stopReason,
1111
+ text: this.text,
1112
+ toolCalls: this.toolCalls,
1113
+ inputTokens: this.inputTokens,
1114
+ outputTokens: this.outputTokens
1115
+ });
1116
+ }
1117
+ };
1118
+ function parseOllamaToolArguments(raw) {
1119
+ try {
1120
+ const parsed = JSON.parse(raw);
1121
+ return typeof parsed === "object" && parsed !== null ? parsed : {};
1122
+ } catch {
1123
+ return {};
1124
+ }
1125
+ }
1126
+ function mapOllamaDoneReason(reason, hasToolCalls) {
1127
+ if (hasToolCalls) return "tool_use";
1128
+ if (reason === "length") return "max_tokens";
1129
+ if (reason === "stop") return "end_turn";
1130
+ return "end_turn";
1131
+ }
1132
+ async function* parseNdjsonStream(body, signal) {
1133
+ const reader = body.getReader();
1134
+ const decoder = new TextDecoder("utf-8");
1135
+ let buffer = "";
1136
+ try {
1137
+ while (true) {
1138
+ if (signal.aborted) return;
1139
+ const { done, value } = await reader.read();
1140
+ if (done) break;
1141
+ buffer += decoder.decode(value, { stream: true });
1142
+ const lines = buffer.split("\n");
1143
+ buffer = lines.pop() ?? "";
1144
+ for (const line of lines) {
1145
+ const trimmed = line.trim();
1146
+ if (trimmed.length === 0) continue;
1147
+ try {
1148
+ yield JSON.parse(trimmed);
1149
+ } catch {
1150
+ }
1151
+ }
1152
+ }
1153
+ const tail = buffer.trim();
1154
+ if (tail.length > 0) {
1155
+ try {
1156
+ yield JSON.parse(tail);
1157
+ } catch {
1158
+ }
1159
+ }
1160
+ } finally {
1161
+ try {
1162
+ await reader.cancel();
1163
+ } catch {
1164
+ }
1165
+ reader.releaseLock();
1166
+ }
1167
+ }
1168
+ var ollamaSystemText = collapseSystemText;
1169
+ function buildOllamaChatBody(request) {
1170
+ const messages = [];
1171
+ const systemText = ollamaSystemText(request.system);
1172
+ if (systemText.length > 0) {
1173
+ messages.push({ role: "system", content: systemText });
1174
+ }
1175
+ for (const message of request.messages) {
1176
+ for (const out of toOllamaMessages(message)) messages.push(out);
1177
+ }
1178
+ const tools = toOllamaTools(request.tools);
1179
+ const body = {
1180
+ model: request.model,
1181
+ stream: true,
1182
+ messages,
1183
+ // ADR D192: 24h keep_alive prevents Ollama from evicting the chat model
1184
+ // when other models (embeddings, judges) are loaded between turns.
1185
+ // Cuts cold-load latency from 20-30s to single-digit ms per turn.
1186
+ keep_alive: process.env.OLLAMA_KEEP_ALIVE ?? "24h"
1187
+ };
1188
+ if (tools.length > 0) body.tools = tools;
1189
+ const opts = {};
1190
+ if (request.maxTokens !== void 0) opts.num_predict = request.maxTokens;
1191
+ if (request.temperature !== void 0) opts.temperature = request.temperature;
1192
+ if (Object.keys(opts).length > 0) body.options = opts;
1193
+ return body;
1194
+ }
1195
+ function toOllamaMessages(message) {
1196
+ if (message.role === "system") {
1197
+ return [{ role: "system", content: joinTextParts(message) }];
1198
+ }
1199
+ if (message.role === "user") {
1200
+ if (message.content.some((p) => p.type === "image")) {
1201
+ throw new chunkA44COQJJ_cjs.ConfigurationError(
1202
+ "image input is not supported on the ollama-native provider; use an OpenAI/OpenRouter model for multimodal turns",
1203
+ { code: "ollama_image_unsupported" }
1204
+ );
1205
+ }
1206
+ const out = [];
1207
+ for (const part of message.content) {
1208
+ if (part.type === "tool_result") {
1209
+ out.push({
1210
+ role: "tool",
1211
+ // SE7 — string-only tool role: text blocks flatten; image fails fast.
1212
+ content: toStringToolResultContent(part.content, "ollama"),
1213
+ tool_name: part.toolUseId
1214
+ });
1215
+ }
1216
+ }
1217
+ const userText = joinTextParts(message);
1218
+ if (userText.length > 0) out.push({ role: "user", content: userText });
1219
+ return out;
1220
+ }
1221
+ const text = joinTextParts(message);
1222
+ const toolCalls = [];
1223
+ for (const part of message.content) {
1224
+ if (part.type === "tool_use") {
1225
+ toolCalls.push({
1226
+ function: { name: part.name, arguments: part.input }
1227
+ });
1228
+ }
1229
+ }
1230
+ const msg = { role: "assistant", content: text };
1231
+ if (toolCalls.length > 0) msg.tool_calls = toolCalls;
1232
+ return [msg];
1233
+ }
1234
+ function joinTextParts(message) {
1235
+ return message.content.filter((p) => p.type === "text").map((p) => p.text).join("\n");
1236
+ }
1237
+ function toOllamaTools(tools) {
1238
+ if (tools === void 0 || tools.length === 0) return [];
1239
+ return tools.map((tool) => ({
1240
+ type: "function",
1241
+ function: {
1242
+ name: tool.name,
1243
+ description: tool.description,
1244
+ parameters: tool.inputSchema
1245
+ }
1246
+ }));
1247
+ }
1248
+
1249
+ // src/internal/llm/hermes-tool-extract.ts
1250
+ var HERMES_BLOCK = /<function=\s*([^>\s]+)\s*>([\s\S]*?)<\/tool_call>/g;
1251
+ var HERMES_PARAM = /<parameter=\s*([^>\s]+)\s*>([\s\S]*?)<\/parameter>/g;
1252
+ function extractHermesToolCalls(content, makeId, allowedToolNames) {
1253
+ const isPromoted = (name) => name.length > 0 && (allowedToolNames === void 0 || allowedToolNames.has(name));
1254
+ const toolCalls = [];
1255
+ const droppedNames = [];
1256
+ for (const block of content.matchAll(HERMES_BLOCK)) {
1257
+ const name = (block[1] ?? "").trim();
1258
+ if (!isPromoted(name)) {
1259
+ if (name.length > 0 && allowedToolNames !== void 0) droppedNames.push(name);
1260
+ continue;
1261
+ }
1262
+ toolCalls.push({
1263
+ type: "tool_use",
1264
+ id: makeId(),
1265
+ name,
1266
+ input: parseHermesParams(block[2] ?? "")
1267
+ });
1268
+ }
1269
+ const residualText = toolCalls.length === 0 ? content : content.replace(
1270
+ HERMES_BLOCK,
1271
+ (full, rawName) => isPromoted((rawName ?? "").trim()) ? "" : full
1272
+ ).trim();
1273
+ return { toolCalls, residualText, droppedNames };
1274
+ }
1275
+ function parseHermesParams(inner) {
1276
+ const input = {};
1277
+ for (const param of inner.matchAll(HERMES_PARAM)) {
1278
+ const key = param[1];
1279
+ const value = param[2];
1280
+ if (key === void 0 || value === void 0) continue;
1281
+ input[key.trim()] = value;
1282
+ }
1283
+ return chunk6JSIEDKL_cjs.sanitizeToolInput(input, { trim: true }).value;
1284
+ }
1285
+ var STREAM_MARKER = "<function=";
1286
+ var DEFAULT_STREAM_BUFFER_CAP = 8192;
1287
+ var isStreamWs = (c) => c === " " || c === " " || c === "\n" || c === "\r";
1288
+ function streamToolCallBufferState(held, allowedToolNames, cap = DEFAULT_STREAM_BUFFER_CAP) {
1289
+ if (allowedToolNames.size === 0) return "impossible";
1290
+ const t = held.trimStart();
1291
+ if (t.length < STREAM_MARKER.length) {
1292
+ return STREAM_MARKER.startsWith(t) ? "possible" : "impossible";
1293
+ }
1294
+ if (!t.startsWith(STREAM_MARKER)) return "impossible";
1295
+ const parsed = parseStreamMarkerName(t);
1296
+ if (parsed === "building") return "possible";
1297
+ if (parsed === "invalid") return "impossible";
1298
+ const nameOk = parsed.complete ? allowedToolNames.has(parsed.name) : someToolNameStartsWith(allowedToolNames, parsed.name);
1299
+ if (!nameOk) return "impossible";
1300
+ return held.length > cap ? "impossible" : "possible";
1301
+ }
1302
+ function parseStreamMarkerName(t) {
1303
+ let cursor = STREAM_MARKER.length;
1304
+ while (cursor < t.length && isStreamWs(t[cursor])) cursor += 1;
1305
+ const nameStart = cursor;
1306
+ while (cursor < t.length && t[cursor] !== ">" && !isStreamWs(t[cursor])) cursor += 1;
1307
+ const name = t.slice(nameStart, cursor);
1308
+ if (name.length === 0) return cursor >= t.length ? "building" : "invalid";
1309
+ return { name, complete: cursor < t.length && t[cursor] === ">" };
1310
+ }
1311
+ function someToolNameStartsWith(allowedToolNames, prefix) {
1312
+ for (const name of allowedToolNames) {
1313
+ if (name.startsWith(prefix)) return true;
1314
+ }
1315
+ return false;
1316
+ }
1317
+ function firstPossibleMarkerStart(held, allowedToolNames) {
1318
+ for (let i = held.indexOf("<"); i !== -1; i = held.indexOf("<", i + 1)) {
1319
+ if (streamToolCallBufferState(held.slice(i), allowedToolNames) === "possible") return i;
1320
+ }
1321
+ return -1;
1322
+ }
1323
+ var StreamSuppressionBuffer = class {
1324
+ constructor(allowedToolNames) {
1325
+ this.allowedToolNames = allowedToolNames;
1326
+ }
1327
+ allowedToolNames;
1328
+ #held = "";
1329
+ /** Feed a content delta; returns the text to emit as a `text_delta` now, or `undefined` to hold. */
1330
+ push(content) {
1331
+ this.#held += content;
1332
+ if (streamToolCallBufferState(this.#held, this.allowedToolNames) === "possible")
1333
+ return void 0;
1334
+ const holdStart = firstPossibleMarkerStart(this.#held, this.allowedToolNames);
1335
+ if (holdStart > 0) {
1336
+ const flush2 = this.#held.slice(0, holdStart);
1337
+ this.#held = this.#held.slice(holdStart);
1338
+ return flush2;
1339
+ }
1340
+ const flush = this.#held;
1341
+ this.#held = "";
1342
+ return flush;
1343
+ }
1344
+ /** Drain the held buffer at stream end. `hasNativeCalls` mirrors `finish()`'s size-guard: when
1345
+ * native `tool_calls` exist, `finish()` won't strip the leaked block, so stream the held text WHOLE
1346
+ * (keeping `accumulatedText == finish.text`); otherwise strip the recoverable blocks. Idempotent. */
1347
+ drain(hasNativeCalls) {
1348
+ if (this.#held.length === 0) return void 0;
1349
+ const held = this.#held;
1350
+ this.#held = "";
1351
+ if (hasNativeCalls) return held;
1352
+ const residual = extractHermesToolCalls(held, () => "held", this.allowedToolNames).residualText;
1353
+ return residual.length > 0 ? residual : void 0;
1354
+ }
1355
+ };
1356
+
1357
+ // src/internal/llm/openai-messages.ts
1358
+ function toOpenAIMessages(message) {
1359
+ if (message.role === "system") return [systemMessage(message)];
1360
+ if (message.role === "user") return userOrToolMessages(message);
1361
+ return [assistantMessage(message)];
1362
+ }
1363
+ function systemMessage(message) {
1364
+ return { role: "system", content: joinTextParts2(message) };
1365
+ }
1366
+ function joinTextParts2(message) {
1367
+ return message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
1368
+ }
1369
+ function userOrToolMessages(message) {
1370
+ const out = [];
1371
+ for (const part of message.content) {
1372
+ if (part.type === "tool_result") {
1373
+ out.push({
1374
+ role: "tool",
1375
+ tool_call_id: part.toolUseId,
1376
+ // SE7 — this wire's tool role is string-only: text blocks flatten; an
1377
+ // image block fails fast (ConfigurationError).
1378
+ content: toStringToolResultContent(part.content, "openai")
1379
+ });
1380
+ }
1381
+ }
1382
+ const userText = joinTextParts2(message);
1383
+ const imageParts = message.content.filter(
1384
+ (p) => p.type === "image"
1385
+ );
1386
+ if (imageParts.length > 0) {
1387
+ const content = [];
1388
+ if (userText.length > 0) content.push({ type: "text", text: userText });
1389
+ for (const img of imageParts) {
1390
+ const url = img.source.type === "base64" ? `data:${img.source.media_type};base64,${img.source.data}` : img.source.url;
1391
+ content.push({ type: "image_url", image_url: { url } });
1392
+ }
1393
+ out.push({ role: "user", content });
1394
+ } else if (userText.length > 0) {
1395
+ out.push({ role: "user", content: userText });
1396
+ }
1397
+ return out;
1398
+ }
1399
+ function assistantMessage(message) {
1400
+ const text = joinTextParts2(message);
1401
+ const toolCalls = message.content.filter((part) => part.type === "tool_use").map((part) => {
1402
+ const tc = part;
1403
+ return {
1404
+ id: tc.id,
1405
+ type: "function",
1406
+ function: { name: tc.name, arguments: JSON.stringify(tc.input) }
1407
+ };
1408
+ });
1409
+ const result = { role: "assistant", content: text };
1410
+ if (toolCalls.length > 0) result.tool_calls = toolCalls;
1411
+ return result;
1412
+ }
1413
+
1414
+ // src/internal/llm/openai.ts
1415
+ function deriveChatPath(baseUrl) {
1416
+ try {
1417
+ return /\/v\d+[a-z]*(\/|$)/.test(new URL(baseUrl).pathname) ? "/chat/completions" : "/v1/chat/completions";
1418
+ } catch {
1419
+ return "/v1/chat/completions";
1420
+ }
1421
+ }
1422
+ var OpenAIClient = class {
1423
+ constructor(options) {
1424
+ this.options = options;
1425
+ this.baseUrl = (options.baseUrl ?? "https://api.openai.com").replace(/\/+$/, "");
1426
+ this.chatPath = options.chatCompletionsPath ?? deriveChatPath(this.baseUrl);
1427
+ this.fetchImpl = options.fetch ?? fetch;
1428
+ }
1429
+ options;
1430
+ name = "openai";
1431
+ baseUrl;
1432
+ chatPath;
1433
+ fetchImpl;
1434
+ /**
1435
+ * Whether this client recovers leaked Hermes tool-call dialect from assistant
1436
+ * text (theokit#58 follow-up). Observability for the route→client wiring of
1437
+ * `extractToolCallsFromContent`. @internal
1438
+ */
1439
+ get recoversLeakedToolCalls() {
1440
+ return this.options.extractToolCallsFromContent ?? false;
1441
+ }
1442
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: HTTP+SSE handshake + accumulator is intentionally one block
1443
+ async *stream(request, signal) {
1444
+ const headers = {
1445
+ "content-type": "application/json",
1446
+ authorization: `Bearer ${this.options.apiKey}`
1447
+ };
1448
+ if (this.options.organization !== void 0) {
1449
+ headers["openai-organization"] = this.options.organization;
1450
+ }
1451
+ if (this.options.extraHeaders !== void 0) Object.assign(headers, this.options.extraHeaders);
1452
+ const providerId = this.options.providerName ?? this.name;
1453
+ let response;
1454
+ try {
1455
+ response = await this.fetchImpl(`${this.baseUrl}${this.chatPath}`, {
1456
+ method: "POST",
1457
+ signal,
1458
+ headers,
1459
+ body: JSON.stringify(buildOpenAIBody(request, providerId))
1460
+ });
1461
+ } catch (fetchErr) {
1462
+ const mapped = mapOllamaTransportError({
1463
+ providerId,
1464
+ cause: fetchErr,
1465
+ endpoint: "/v1/chat/completions"
1466
+ });
1467
+ if (mapped !== void 0) throw mapped;
1468
+ throw fetchErr;
1469
+ }
1470
+ if (!response.ok) {
1471
+ const text = await response.text().catch(() => "");
1472
+ let body = text;
1473
+ try {
1474
+ body = JSON.parse(text);
1475
+ } catch {
1476
+ }
1477
+ const ollamaMapped = mapOllamaHttpError({
1478
+ providerId,
1479
+ status: response.status,
1480
+ body,
1481
+ headers: response.headers,
1482
+ endpoint: "/v1/chat/completions"
1483
+ });
1484
+ if (ollamaMapped !== void 0) throw ollamaMapped;
1485
+ throw mapOpenAICompatibleError({
1486
+ providerId,
1487
+ status: response.status,
1488
+ body,
1489
+ headers: response.headers,
1490
+ endpoint: "/v1/chat/completions"
1491
+ });
1492
+ }
1493
+ const accumulator = new OpenAIStreamAccumulator(
1494
+ this.options.extractToolCallsFromContent ?? false,
1495
+ providerId,
1496
+ // R5: request-scoped allowlist — leaked recovery only promotes a block whose name is a tool the
1497
+ // model was actually given. Empty set (no tools) recovers nothing.
1498
+ new Set(request.tools?.map((tool) => tool.name) ?? [])
1499
+ );
1500
+ let sawDone = false;
1501
+ for await (const record of parseSseStream(response.body, signal)) {
1502
+ if (record.data === "[DONE]") {
1503
+ sawDone = true;
1504
+ break;
1505
+ }
1506
+ let chunk;
1507
+ try {
1508
+ chunk = JSON.parse(record.data);
1509
+ } catch {
1510
+ continue;
1511
+ }
1512
+ if (chunk.error !== void 0 && chunk.error !== null) {
1513
+ const status = typeof chunk.error.code === "number" ? chunk.error.code : 502;
1514
+ throw mapOpenAICompatibleError({
1515
+ providerId,
1516
+ status,
1517
+ body: chunk,
1518
+ headers: response.headers,
1519
+ endpoint: "/v1/chat/completions"
1520
+ });
1521
+ }
1522
+ const events = accumulator.consume(chunk);
1523
+ for (const event of events) yield event;
1524
+ }
1525
+ if (!sawDone && !accumulator.finishReasonSeen) {
1526
+ throw new chunkA44COQJJ_cjs.NetworkError("SSE stream truncated (no finish_reason / [DONE])", {
1527
+ code: "stream_truncated"
1528
+ });
1529
+ }
1530
+ const drainEvent = accumulator.finalizeHeldText();
1531
+ if (drainEvent !== void 0) yield drainEvent;
1532
+ return accumulator.finish();
1533
+ }
1534
+ };
1535
+ var OpenAIStreamAccumulator = class {
1536
+ /**
1537
+ * @param extractFromContent opt-in leaked-dialect safe-parse (theokit#58). Default false.
1538
+ * @param providerName provider id, used only to label the recovery log line.
1539
+ * @param allowedToolNames R5 request-scoped allowlist — built from `request.tools` at `stream()`;
1540
+ * leaked recovery in `finish()` only promotes a block whose name is in this set. `undefined`
1541
+ * (direct construction) recovers all (back-compat); an empty set recovers nothing.
1542
+ */
1543
+ constructor(extractFromContent = false, providerName = "openai", allowedToolNames) {
1544
+ this.extractFromContent = extractFromContent;
1545
+ this.providerName = providerName;
1546
+ this.allowedToolNames = allowedToolNames;
1547
+ this.suppress = extractFromContent && allowedToolNames !== void 0 && allowedToolNames.size > 0 ? new StreamSuppressionBuffer(allowedToolNames) : void 0;
1548
+ }
1549
+ extractFromContent;
1550
+ providerName;
1551
+ allowedToolNames;
1552
+ text = "";
1553
+ stopReason = "end_turn";
1554
+ inputTokens;
1555
+ outputTokens;
1556
+ cacheReadTokens;
1557
+ cacheWriteTokens;
1558
+ reasoningTokens;
1559
+ toolCalls = /* @__PURE__ */ new Map();
1560
+ /** R7: present only when recovery is enabled AND the request declares tools — holds suspected
1561
+ * leaked-dialect content back from the `text_delta` stream. `undefined` ⇒ stream immediately. */
1562
+ suppress;
1563
+ consume(chunk) {
1564
+ const events = [];
1565
+ this.applyUsage(chunk.usage);
1566
+ for (const choice of chunk.choices ?? []) {
1567
+ events.push(...this.applyChoice(choice));
1568
+ }
1569
+ return events;
1570
+ }
1571
+ applyChoice(choice) {
1572
+ const events = [];
1573
+ const reasoningEvent = this.applyReasoningDelta(
1574
+ choice.delta?.reasoning ?? choice.delta?.reasoning_content
1575
+ );
1576
+ if (reasoningEvent !== void 0) events.push(reasoningEvent);
1577
+ const textEvent = this.applyContentDelta(choice.delta?.content);
1578
+ if (textEvent !== void 0) events.push(textEvent);
1579
+ this.mergeToolCallDeltas(choice.delta?.tool_calls);
1580
+ this.applyFinishReason(choice.finish_reason);
1581
+ if (choice.finish_reason !== void 0 && choice.finish_reason !== null) {
1582
+ const flushEvent = this.finalizeHeldText();
1583
+ if (flushEvent !== void 0) events.push(flushEvent);
1584
+ }
1585
+ return events;
1586
+ }
1587
+ applyReasoningDelta(reasoning) {
1588
+ if (typeof reasoning !== "string" || reasoning.length === 0) return void 0;
1589
+ return { type: "reasoning_delta", text: reasoning };
1590
+ }
1591
+ applyUsage(usage) {
1592
+ if (usage?.prompt_tokens !== void 0) this.inputTokens = usage.prompt_tokens;
1593
+ if (usage?.completion_tokens !== void 0) this.outputTokens = usage.completion_tokens;
1594
+ const cachedDetail = usage?.prompt_tokens_details?.cached_tokens;
1595
+ if (cachedDetail !== void 0) this.cacheReadTokens = cachedDetail;
1596
+ const reasoningDetail = usage?.completion_tokens_details?.reasoning_tokens;
1597
+ if (reasoningDetail !== void 0) this.reasoningTokens = reasoningDetail;
1598
+ if (usage?.cache_read_input_tokens !== void 0) {
1599
+ this.cacheReadTokens = usage.cache_read_input_tokens;
1600
+ }
1601
+ if (usage?.cache_creation_input_tokens !== void 0) {
1602
+ this.cacheWriteTokens = usage.cache_creation_input_tokens;
1603
+ }
1604
+ }
1605
+ applyContentDelta(content) {
1606
+ if (typeof content !== "string" || content.length === 0) return void 0;
1607
+ this.text += content;
1608
+ if (this.suppress === void 0) return { type: "text_delta", text: content };
1609
+ const emit = this.suppress.push(content);
1610
+ return emit !== void 0 ? { type: "text_delta", text: emit } : void 0;
1611
+ }
1612
+ /** R7 held-buffer finalizer, called at the `finish_reason` chunk (in `applyChoice`) AND after the
1613
+ * SSE loop in `stream()` — so a stream that omits a `finish_reason` terminal never silently drops
1614
+ * held text. `toolCalls.size > 0` (native calls present) makes `finish()` skip recovery, so the
1615
+ * buffer streams the held text whole. Idempotent once drained. */
1616
+ finalizeHeldText() {
1617
+ const emit = this.suppress?.drain(this.toolCalls.size > 0);
1618
+ return emit !== void 0 ? { type: "text_delta", text: emit } : void 0;
1619
+ }
1620
+ mergeToolCallDeltas(deltas) {
1621
+ for (const call of deltas ?? []) {
1622
+ const existing = this.toolCalls.get(call.index) ?? { id: "", name: "", args: "" };
1623
+ if (call.id !== void 0) existing.id = call.id;
1624
+ if (call.function?.name !== void 0) existing.name = call.function.name;
1625
+ if (call.function?.arguments !== void 0) existing.args += call.function.arguments;
1626
+ this.toolCalls.set(call.index, existing);
1627
+ }
1628
+ }
1629
+ /** M2 #61 — true once any chunk carried a non-null `finish_reason` (else a
1630
+ * stream ending without `[DONE]` is a truncation, not a clean end). */
1631
+ sawFinishReason = false;
1632
+ get finishReasonSeen() {
1633
+ return this.sawFinishReason;
1634
+ }
1635
+ applyFinishReason(reason) {
1636
+ if (reason === void 0 || reason === null) return;
1637
+ this.sawFinishReason = true;
1638
+ this.stopReason = mapOpenAIFinish(reason);
1639
+ }
1640
+ finish() {
1641
+ const toolCalls = [];
1642
+ for (const call of this.toolCalls.values()) {
1643
+ const input = parseToolArguments(call.args);
1644
+ toolCalls.push({ type: "tool_use", id: call.id, name: call.name, input });
1645
+ }
1646
+ let text = this.text;
1647
+ let stopReason = this.stopReason;
1648
+ if (this.extractFromContent && toolCalls.length === 0) {
1649
+ const recovered = extractHermesToolCalls(
1650
+ this.text,
1651
+ () => `hermes-${globalThis.crypto.randomUUID()}`,
1652
+ this.allowedToolNames
1653
+ );
1654
+ if (recovered.toolCalls.length > 0) {
1655
+ toolCalls.push(...recovered.toolCalls);
1656
+ text = recovered.residualText;
1657
+ stopReason = "tool_use";
1658
+ process.stderr.write(
1659
+ `[theokit-sdk] recovered ${recovered.toolCalls.length} leaked tool call(s) from assistant content (provider="${this.providerName}", names=${recovered.toolCalls.map((c) => c.name).join(",")})
1660
+ `
1661
+ );
1662
+ }
1663
+ if (recovered.droppedNames.length > 0) {
1664
+ process.stderr.write(
1665
+ `[theokit-sdk] dropped ${recovered.droppedNames.length} leaked block(s) whose name is not a tool in the request (provider="${this.providerName}", names=${recovered.droppedNames.join(",")})
1666
+ `
1667
+ );
1668
+ }
1669
+ }
1670
+ return makeLlmFinish({
1671
+ stopReason,
1672
+ text,
1673
+ toolCalls,
1674
+ inputTokens: this.inputTokens,
1675
+ outputTokens: this.outputTokens,
1676
+ cacheReadTokens: this.cacheReadTokens,
1677
+ cacheWriteTokens: this.cacheWriteTokens,
1678
+ reasoningTokens: this.reasoningTokens
1679
+ });
1680
+ }
1681
+ };
1682
+ function applyReasoningRequest(body, effort, providerName) {
1683
+ if (providerName === "openai") {
1684
+ body.reasoning_effort = effort;
1685
+ return;
1686
+ }
1687
+ body.reasoning = { effort };
1688
+ }
1689
+ function applyToolsRequest(body, request) {
1690
+ if (request.tools === void 0 || request.tools.length === 0) return;
1691
+ body.tools = request.tools.map((tool) => ({
1692
+ type: "function",
1693
+ function: { name: tool.name, description: tool.description, parameters: tool.inputSchema }
1694
+ }));
1695
+ if (request.toolChoice !== void 0) body.tool_choice = request.toolChoice;
1696
+ }
1697
+ function buildOpenAIBody(request, providerName) {
1698
+ const messages = [];
1699
+ const systemText = openAISystemText(request.system);
1700
+ if (systemText.length > 0) {
1701
+ messages.push({ role: "system", content: systemText });
1702
+ }
1703
+ for (const message of request.messages) {
1704
+ for (const out of toOpenAIMessages(message)) messages.push(out);
1705
+ }
1706
+ const body = {
1707
+ model: request.model,
1708
+ stream: true,
1709
+ // D376: opt-in to OpenAI's final-chunk usage record (no-op for providers
1710
+ // that don't honor it; OpenRouter / OpenAI both respect it).
1711
+ stream_options: { include_usage: true },
1712
+ messages
1713
+ };
1714
+ if (request.maxTokens !== void 0) body.max_tokens = request.maxTokens;
1715
+ if (request.temperature !== void 0) body.temperature = request.temperature;
1716
+ if (request.reasoning?.effort !== void 0)
1717
+ applyReasoningRequest(body, request.reasoning.effort, providerName);
1718
+ applyToolsRequest(body, request);
1719
+ const responseFormat = encodeOpenAIResponseFormat(request.responseFormat);
1720
+ if (responseFormat !== void 0) body.response_format = responseFormat;
1721
+ return body;
1722
+ }
1723
+ var openAISystemText = collapseSystemText;
1724
+ function encodeOpenAIResponseFormat(rf) {
1725
+ if (rf === void 0) return void 0;
1726
+ if (rf.type === "json_object") return { type: "json_object" };
1727
+ return {
1728
+ type: "json_schema",
1729
+ json_schema: {
1730
+ name: rf.jsonSchema.name,
1731
+ schema: rf.jsonSchema.schema,
1732
+ strict: rf.jsonSchema.strict ?? true
1733
+ }
1734
+ };
1735
+ }
1736
+
1737
+ // src/internal/resilience/circuit-breaker.ts
1738
+ var DEFAULT_MAX_TIMEOUTS = 3;
1739
+ var DEFAULT_COOLDOWN_MS = 6e4;
1740
+ var CircuitBreaker = class {
1741
+ constructor(opts = {}) {
1742
+ this.opts = opts;
1743
+ }
1744
+ opts;
1745
+ states = /* @__PURE__ */ new Map();
1746
+ /** @returns true when the breaker is open and the call should be skipped. */
1747
+ shouldSkip(key) {
1748
+ const state = this.states.get(key);
1749
+ if (state === void 0) return false;
1750
+ if (state.cooldownUntilMs === 0) return false;
1751
+ if (this.now() < state.cooldownUntilMs) return true;
1752
+ state.cooldownUntilMs = 0;
1753
+ state.consecutiveTimeouts = 0;
1754
+ return false;
1755
+ }
1756
+ recordSuccess(key) {
1757
+ const state = this.states.get(key);
1758
+ if (state === void 0) return;
1759
+ state.consecutiveTimeouts = 0;
1760
+ state.cooldownUntilMs = 0;
1761
+ }
1762
+ recordTimeout(key) {
1763
+ const state = this.states.get(key) ?? { consecutiveTimeouts: 0, cooldownUntilMs: 0 };
1764
+ state.consecutiveTimeouts += 1;
1765
+ if (state.consecutiveTimeouts >= (this.opts.maxTimeouts ?? DEFAULT_MAX_TIMEOUTS)) {
1766
+ state.cooldownUntilMs = this.now() + (this.opts.cooldownMs ?? DEFAULT_COOLDOWN_MS);
1767
+ }
1768
+ this.states.set(key, state);
1769
+ }
1770
+ /** @internal — tests inspect counter state. */
1771
+ inspect(key) {
1772
+ return this.states.get(key) ?? { consecutiveTimeouts: 0, cooldownUntilMs: 0 };
1773
+ }
1774
+ now() {
1775
+ return this.opts.now?.() ?? Date.now();
1776
+ }
1777
+ };
1778
+
1779
+ // src/internal/llm/stream-relay.ts
1780
+ async function tryFirstEvent(client, request, signal, logFallback = false) {
1781
+ const generator = client.stream(request, signal);
1782
+ try {
1783
+ const firstResult = await generator.next();
1784
+ return { kind: "ok", generator, firstResult };
1785
+ } catch (cause) {
1786
+ if (cause instanceof chunkA44COQJJ_cjs.NetworkError || cause instanceof chunkA44COQJJ_cjs.RateLimitError || cause instanceof chunkA44COQJJ_cjs.AuthenticationError) {
1787
+ if (logFallback) {
1788
+ const errCode = cause.metadata?.code ?? cause.code ?? "unknown";
1789
+ process.stderr.write(
1790
+ `[theokit-sdk] provider ${client.name} failed (${errCode}): falling back
1791
+ `
1792
+ );
1793
+ }
1794
+ return { kind: "handshake_error", error: cause };
1795
+ }
1796
+ throw cause;
1797
+ }
1798
+ }
1799
+ async function* relayStream(generator, firstResult) {
1800
+ if (firstResult.done === true) return firstResult.value;
1801
+ yield firstResult.value;
1802
+ while (true) {
1803
+ const next = await generator.next();
1804
+ if (next.done === true) return next.value;
1805
+ yield next.value;
1806
+ }
1807
+ }
1808
+
1809
+ // src/internal/llm/pool-aware-client.ts
1810
+ var PoolAwareLlmClient = class {
1811
+ constructor(pool, buildClient2, waitForAvailableMs = 3e4, resilience = {}) {
1812
+ this.pool = pool;
1813
+ this.buildClient = buildClient2;
1814
+ this.waitForAvailableMs = waitForAvailableMs;
1815
+ this.name = `pool-aware:${pool.provider}`;
1816
+ this.breaker = resilience.breaker ?? new CircuitBreaker();
1817
+ this.backoffBaseMs = resilience.backoffBaseMs;
1818
+ this.rng = resilience.rng;
1819
+ this.onRateLimit = resilience.onRateLimit;
1820
+ }
1821
+ pool;
1822
+ buildClient;
1823
+ waitForAvailableMs;
1824
+ name;
1825
+ onRateLimit;
1826
+ /** M2 #60 — provider-level circuit breaker (consecutive-failure). */
1827
+ breaker;
1828
+ backoffBaseMs;
1829
+ rng;
1830
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: stream() must serialize pool-select → build client → first-event probe → classify → retry/rotate/propagate. Extracting helpers fragments the linear narrative; the comments above each branch keep it readable.
1831
+ async *stream(request, signal) {
1832
+ if (this.breaker.shouldSkip(this.pool.provider)) {
1833
+ throw new chunkA44COQJJ_cjs.NetworkError(`${this.pool.provider} circuit open \u2014 failing fast`, {
1834
+ code: "circuit_open"
1835
+ });
1836
+ }
1837
+ let hasRetried429 = false;
1838
+ while (true) {
1839
+ if (signal.aborted) throw abortError(signal);
1840
+ let entry = await this.pool.select();
1841
+ if (entry === null) {
1842
+ if (this.waitForAvailableMs > 0) {
1843
+ const available = await this.pool.waitForAvailable(signal, {
1844
+ maxWaitMs: this.waitForAvailableMs
1845
+ });
1846
+ if (available) {
1847
+ entry = await this.pool.select();
1848
+ }
1849
+ }
1850
+ if (entry === null) {
1851
+ this.breaker.recordTimeout(this.pool.provider);
1852
+ throw new chunkA44COQJJ_cjs.CredentialPoolExhaustedError(
1853
+ `All ${this.pool.provider} credentials exhausted; next retry available at ${this.nextRetryHint() ?? "unknown"}`,
1854
+ { provider: this.pool.provider, nextRetryAt: this.nextRetryHint() }
1855
+ );
1856
+ }
1857
+ }
1858
+ const realClient = this.buildClient(entry.accessToken);
1859
+ const attempt = await tryFirstEvent(realClient, request, signal);
1860
+ if (attempt.kind === "ok") {
1861
+ this.breaker.recordSuccess(this.pool.provider);
1862
+ return yield* relayStream(attempt.generator, attempt.firstResult);
1863
+ }
1864
+ const decision = classifyAndDecide(attempt.error, hasRetried429);
1865
+ if (decision === "retry") {
1866
+ const backoffMs = chunkLUSXDZPV_cjs.computeBackoffMs({
1867
+ attempt: 0,
1868
+ ...this.backoffBaseMs !== void 0 ? { baseMs: this.backoffBaseMs } : {},
1869
+ ...this.rng !== void 0 ? { rng: this.rng } : {}
1870
+ });
1871
+ this.onRateLimit?.({ attempt: 1, retryAfterMs: backoffMs });
1872
+ await chunkLUSXDZPV_cjs.sleepWithAbort(backoffMs, signal);
1873
+ hasRetried429 = true;
1874
+ continue;
1875
+ }
1876
+ if (decision === "rotate") {
1877
+ try {
1878
+ await this.pool.markExhaustedAndRotate({
1879
+ entryId: entry.id,
1880
+ statusCode: attempt.error.metadata?.statusCode ?? inferStatusCode(attempt.error),
1881
+ ...parseRetryAfterMs(attempt.error) !== void 0 ? { resetAtMs: parseRetryAfterMs(attempt.error) } : {}
1882
+ });
1883
+ } catch (persistErr) {
1884
+ process.stderr.write(
1885
+ `[theokit-sdk] credential-pool: persist failed during rotate; continuing in-memory: ${persistErr instanceof Error ? persistErr.message : String(persistErr)}
1886
+ `
1887
+ );
1888
+ }
1889
+ hasRetried429 = false;
1890
+ continue;
1891
+ }
1892
+ this.breaker.recordTimeout(this.pool.provider);
1893
+ throw attempt.error;
1894
+ }
1895
+ }
1896
+ /**
1897
+ * Earliest epoch ms among entries' `lastErrorResetAt` — best estimate
1898
+ * for the caller's `CredentialPoolExhaustedError.nextRetryAt`.
1899
+ */
1900
+ nextRetryHint() {
1901
+ const resets = this.pool.list().map((e) => e.lastErrorResetAt).filter((v) => v !== void 0);
1902
+ return resets.length === 0 ? void 0 : Math.min(...resets);
1903
+ }
1904
+ };
1905
+ function classifyAndDecide(error, hasRetried429) {
1906
+ if (error instanceof chunkA44COQJJ_cjs.NetworkError) return "propagate";
1907
+ if (error instanceof chunkA44COQJJ_cjs.AuthenticationError) return "rotate";
1908
+ const status = error.metadata?.statusCode ?? 429;
1909
+ if (status === 402) return "rotate";
1910
+ return hasRetried429 ? "rotate" : "retry";
1911
+ }
1912
+ function parseRetryAfterMs(error) {
1913
+ const seconds = error.metadata?.retryAfter;
1914
+ if (typeof seconds === "number" && seconds > 0) {
1915
+ return Date.now() + seconds * 1e3;
1916
+ }
1917
+ return void 0;
1918
+ }
1919
+ function inferStatusCode(error) {
1920
+ if (error instanceof chunkA44COQJJ_cjs.AuthenticationError) return 401;
1921
+ if (error instanceof chunkA44COQJJ_cjs.RateLimitError) return 429;
1922
+ return 0;
1923
+ }
1924
+ function abortError(signal) {
1925
+ if (signal.reason instanceof Error) return signal.reason;
1926
+ return new Error("AbortError");
1927
+ }
1928
+
1929
+ // src/internal/llm/responses.ts
1930
+ function messageToInputItems(message) {
1931
+ const items = [];
1932
+ if (message.role === "user") {
1933
+ const content = [];
1934
+ for (const part of message.content) {
1935
+ if (part.type === "text") {
1936
+ content.push({ type: "input_text", text: part.text });
1937
+ } else if (part.type === "image") {
1938
+ const url = part.source.type === "base64" ? `data:${part.source.media_type};base64,${part.source.data}` : part.source.url;
1939
+ content.push({ type: "input_image", image_url: url });
1940
+ } else if (part.type === "tool_result") {
1941
+ items.push({
1942
+ type: "function_call_output",
1943
+ call_id: part.toolUseId,
1944
+ output: toStringToolResultContent(part.content, "openai-responses")
1945
+ });
1946
+ }
1947
+ }
1948
+ if (content.length > 0) items.push({ role: "user", content });
1949
+ return items;
1950
+ }
1951
+ if (message.role === "assistant") {
1952
+ const content = [];
1953
+ for (const part of message.content) {
1954
+ if (part.type === "text") {
1955
+ content.push({ type: "output_text", text: part.text });
1956
+ } else if (part.type === "tool_use") {
1957
+ items.push({
1958
+ type: "function_call",
1959
+ call_id: part.id,
1960
+ name: part.name,
1961
+ arguments: JSON.stringify(part.input)
1962
+ });
1963
+ }
1964
+ }
1965
+ if (content.length > 0) items.push({ role: "assistant", content });
1966
+ return items;
1967
+ }
1968
+ const text = message.content.filter((p) => p.type === "text").map((p) => p.text).join("\n");
1969
+ if (text.length > 0) items.push({ role: "system", content: text });
1970
+ return items;
1971
+ }
1972
+ function buildResponsesBody(request) {
1973
+ const input = [];
1974
+ for (const message of request.messages) {
1975
+ for (const item of messageToInputItems(message)) input.push(item);
1976
+ }
1977
+ const slash = request.model.lastIndexOf("/");
1978
+ const model = slash >= 0 ? request.model.slice(slash + 1) : request.model;
1979
+ const body = { model, input, stream: true, store: false };
1980
+ const instructions = collapseSystemText(request.system);
1981
+ if (instructions.length > 0) body.instructions = instructions;
1982
+ if (request.maxTokens !== void 0) body.max_output_tokens = request.maxTokens;
1983
+ if (request.temperature !== void 0) body.temperature = request.temperature;
1984
+ const tools = (request.tools ?? []).map((tool) => ({
1985
+ type: "function",
1986
+ name: tool.name,
1987
+ description: tool.description,
1988
+ parameters: tool.inputSchema,
1989
+ strict: false
1990
+ }));
1991
+ if (tools.length > 0) body.tools = tools;
1992
+ if (request.reasoning !== void 0) body.reasoning = { effort: request.reasoning.effort };
1993
+ return body;
1994
+ }
1995
+ var ResponsesApiClient = class {
1996
+ constructor(options) {
1997
+ this.options = options;
1998
+ this.name = options.providerName ?? "openai-responses";
1999
+ this.baseUrl = (options.baseUrl ?? "https://api.openai.com/v1").replace(/\/+$/, "");
2000
+ this.fetchImpl = options.fetch ?? fetch;
2001
+ }
2002
+ options;
2003
+ name;
2004
+ baseUrl;
2005
+ fetchImpl;
2006
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: the SSE dispatch (text / reasoning / tool-call add+delta+done / terminal+usage / error) is one cohesive state machine, mirroring OpenAIStreamAccumulator.consume.
2007
+ async *stream(request, signal) {
2008
+ const providerId = this.options.providerName ?? "openai";
2009
+ const headers = {
2010
+ "content-type": "application/json",
2011
+ accept: "text/event-stream",
2012
+ authorization: `Bearer ${this.options.apiKey}`,
2013
+ ...this.options.extraHeaders ?? {}
2014
+ };
2015
+ const url = `${this.baseUrl}/responses`;
2016
+ const response = await this.fetchImpl(url, {
2017
+ method: "POST",
2018
+ signal,
2019
+ headers,
2020
+ body: JSON.stringify(buildResponsesBody(request))
2021
+ });
2022
+ if (!response.ok) {
2023
+ const text2 = await response.text().catch(() => "");
2024
+ let body = text2;
2025
+ try {
2026
+ body = JSON.parse(text2);
2027
+ } catch {
2028
+ }
2029
+ throw mapOpenAICompatibleError({
2030
+ providerId,
2031
+ status: response.status,
2032
+ body,
2033
+ headers: response.headers,
2034
+ endpoint: "/responses"
2035
+ });
2036
+ }
2037
+ let text = "";
2038
+ const toolCalls = [];
2039
+ let stopReason = "end_turn";
2040
+ let inputTokens;
2041
+ let outputTokens;
2042
+ let reasoningTokens;
2043
+ const pending = {};
2044
+ if (response.body !== null) {
2045
+ for await (const record of parseSseStream(response.body, signal)) {
2046
+ if (record.data === "[DONE]") break;
2047
+ let event;
2048
+ try {
2049
+ event = JSON.parse(record.data);
2050
+ } catch {
2051
+ continue;
2052
+ }
2053
+ const t = event.type;
2054
+ if (t === "response.output_text.delta") {
2055
+ const d = event.delta ?? "";
2056
+ if (d.length > 0) {
2057
+ text += d;
2058
+ yield { type: "text_delta", text: d };
2059
+ }
2060
+ } else if (t === "response.reasoning_summary_text.delta" || t === "response.reasoning_text.delta") {
2061
+ const d = event.delta ?? "";
2062
+ if (d.length > 0) yield { type: "reasoning_delta", text: d };
2063
+ } else if (t === "response.output_item.added" && event.item?.type === "function_call") {
2064
+ const id = event.item.id ?? event.item.call_id ?? "call-0";
2065
+ pending[id] = {
2066
+ callId: event.item.call_id ?? id,
2067
+ name: event.item.name ?? "",
2068
+ args: event.item.arguments ?? ""
2069
+ };
2070
+ } else if (t === "response.function_call_arguments.delta") {
2071
+ const c = event.item_id !== void 0 ? pending[event.item_id] : void 0;
2072
+ if (c !== void 0) c.args += event.delta ?? "";
2073
+ } else if (t === "response.output_item.done" && event.item?.type === "function_call") {
2074
+ const id = event.item.id ?? event.item.call_id ?? "call-0";
2075
+ const c = pending[id] ?? {
2076
+ callId: event.item.call_id ?? id,
2077
+ name: event.item.name ?? "",
2078
+ args: event.item.arguments ?? ""
2079
+ };
2080
+ const rawArgs = event.item.arguments ?? c.args;
2081
+ const call = {
2082
+ type: "tool_use",
2083
+ id: c.callId,
2084
+ name: c.name.length > 0 ? c.name : event.item.name ?? "",
2085
+ input: parseToolArguments(rawArgs)
2086
+ };
2087
+ toolCalls.push(call);
2088
+ delete pending[id];
2089
+ yield { type: "tool_use", id: call.id, name: call.name, input: call.input };
2090
+ } else if (t === "response.completed" || t === "response.incomplete") {
2091
+ const usage = event.response?.usage;
2092
+ if (usage !== void 0) {
2093
+ inputTokens = usage.input_tokens;
2094
+ outputTokens = usage.output_tokens;
2095
+ reasoningTokens = usage.output_tokens_details?.reasoning_tokens;
2096
+ }
2097
+ stopReason = t === "response.incomplete" ? "max_tokens" : "end_turn";
2098
+ } else if (t === "response.failed" || t === "error") {
2099
+ const msg = event.response?.error?.message ?? event.message ?? "responses stream failed";
2100
+ yield { type: "error", message: msg };
2101
+ throw mapOpenAICompatibleError({
2102
+ providerId,
2103
+ status: 502,
2104
+ body: { error: { message: msg } },
2105
+ headers: response.headers,
2106
+ endpoint: "/responses"
2107
+ });
2108
+ }
2109
+ }
2110
+ }
2111
+ if (toolCalls.length > 0 && stopReason === "end_turn") stopReason = "tool_use";
2112
+ yield { type: "stop", reason: stopReason };
2113
+ return makeLlmFinish({
2114
+ stopReason,
2115
+ text,
2116
+ toolCalls,
2117
+ inputTokens,
2118
+ outputTokens,
2119
+ reasoningTokens
2120
+ });
2121
+ }
2122
+ };
2123
+
2124
+ // src/internal/error-mappers/vertex.ts
2125
+ var VERTEX_RULES = [
2126
+ { test: (s, e) => s === 429 || e === "RESOURCE_EXHAUSTED", code: "rate_limit" },
2127
+ { test: (s, e) => s === 401 || e === "UNAUTHENTICATED", code: "auth_unauthenticated" },
2128
+ { test: (s, e) => s === 403 || e === "PERMISSION_DENIED", code: "auth_permission" },
2129
+ {
2130
+ test: (s, e) => s === 400 || e === "INVALID_ARGUMENT" || e === "FAILED_PRECONDITION" || e === "NOT_FOUND",
2131
+ code: "invalid_request"
2132
+ },
2133
+ { test: (s, e) => s === 408 || e === "DEADLINE_EXCEEDED", code: "timeout" },
2134
+ { test: (s) => s >= 500, code: "server_error" }
2135
+ ];
2136
+ function classifyVertexError(args, errStatus) {
2137
+ for (const rule of VERTEX_RULES) {
2138
+ if (rule.test(args.status, errStatus)) return rule.code;
2139
+ }
2140
+ return "unknown";
2141
+ }
2142
+ function vertexMetadata(args, code) {
2143
+ return buildErrorMetadata({
2144
+ provider: "vertex",
2145
+ endpoint: args.endpoint,
2146
+ code,
2147
+ status: args.status,
2148
+ headers: args.headers,
2149
+ body: args.body
2150
+ });
2151
+ }
2152
+ var VERTEX_ERROR_BUILDERS = {
2153
+ rate_limit: (args, msg) => new chunkA44COQJJ_cjs.RateLimitError(`Vertex quota exhausted: ${msg}`, {
2154
+ metadata: vertexMetadata(args, "rate_limit")
2155
+ }),
2156
+ auth_unauthenticated: (args, msg) => new chunkA44COQJJ_cjs.AuthenticationError(`Vertex unauthenticated: ${msg}`, {
2157
+ metadata: vertexMetadata(args, "auth_failed")
2158
+ }),
2159
+ auth_permission: (args, msg) => new chunkA44COQJJ_cjs.AuthenticationError(`Vertex permission denied: ${msg}`, {
2160
+ metadata: vertexMetadata(args, "auth_failed")
2161
+ }),
2162
+ invalid_request: (args, msg) => new chunkA44COQJJ_cjs.ConfigurationError(`Vertex validation: ${msg}`, {
2163
+ metadata: vertexMetadata(args, "invalid_request")
2164
+ }),
2165
+ timeout: (args, msg) => new chunkA44COQJJ_cjs.NetworkError(`Vertex timeout: ${msg}`, { metadata: vertexMetadata(args, "timeout") }),
2166
+ server_error: (args, msg) => new chunkA44COQJJ_cjs.NetworkError(`Vertex server error: ${msg}`, {
2167
+ metadata: vertexMetadata(args, "server_error")
2168
+ }),
2169
+ unknown: (args, msg) => new chunkA44COQJJ_cjs.UnknownAgentError(`Vertex unknown: ${msg}`, { metadata: vertexMetadata(args, "unknown") })
2170
+ };
2171
+ function mapVertexError(args) {
2172
+ const parsed = parseBody2(args.body);
2173
+ const errStatus = parsed.error?.status ?? "";
2174
+ const message = parsed.error?.message ?? "Vertex request failed";
2175
+ const code = classifyVertexError(args, errStatus);
2176
+ return VERTEX_ERROR_BUILDERS[code](args, message);
2177
+ }
2178
+ function parseBody2(body) {
2179
+ if (body !== null && typeof body === "object") return body;
2180
+ if (typeof body === "string") {
2181
+ try {
2182
+ return JSON.parse(body);
2183
+ } catch {
2184
+ return {};
2185
+ }
2186
+ }
2187
+ return {};
2188
+ }
2189
+ var cachedAuthClient;
2190
+ var SCOPE_CLOUD_PLATFORM = "https://www.googleapis.com/auth/cloud-platform";
2191
+ async function resolveVertexAccessToken() {
2192
+ if (cachedAuthClient === void 0) {
2193
+ cachedAuthClient = await getAuthClientOrThrow();
2194
+ }
2195
+ try {
2196
+ const result = await cachedAuthClient.getAccessToken();
2197
+ return result.token ?? void 0;
2198
+ } catch {
2199
+ return void 0;
2200
+ }
2201
+ }
2202
+ async function getAuthClientOrThrow() {
2203
+ let mod;
2204
+ try {
2205
+ const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-2MF3IE2D.cjs', document.baseURI).href)));
2206
+ mod = r("google-auth-library");
2207
+ } catch (err) {
2208
+ const isModuleMissing = err instanceof Error && (err.message.includes("Cannot find module") || err.code === "MODULE_NOT_FOUND");
2209
+ if (isModuleMissing) {
2210
+ throw new chunkA44COQJJ_cjs.ConfigurationError(
2211
+ "Vertex provider requires `google-auth-library`. Install: `pnpm add google-auth-library`.",
2212
+ { code: "auth_failed", cause: err }
2213
+ );
2214
+ }
2215
+ throw err;
2216
+ }
2217
+ try {
2218
+ const auth = new mod.GoogleAuth({ scopes: [SCOPE_CLOUD_PLATFORM] });
2219
+ return await auth.getClient();
2220
+ } catch (err) {
2221
+ process.stderr.write(
2222
+ `[theokit-sdk] Vertex ADC initialization failed: ${err instanceof Error ? err.message : String(err)}
2223
+ `
2224
+ );
2225
+ return { getAccessToken: async () => ({ token: null }) };
2226
+ }
2227
+ }
2228
+ function resolveVertexProjectId() {
2229
+ return process.env.GOOGLE_CLOUD_PROJECT ?? process.env.GOOGLE_CLOUD_PROJECT_ID ?? process.env.GCLOUD_PROJECT;
2230
+ }
2231
+ function resolveVertexLocation() {
2232
+ return process.env.GOOGLE_CLOUD_LOCATION ?? process.env.CLOUD_ML_REGION ?? "us-central1";
2233
+ }
2234
+
2235
+ // src/internal/llm/vertex-anthropic.ts
2236
+ var VertexAnthropicClient = class {
2237
+ constructor(options) {
2238
+ this.options = options;
2239
+ this.fetchImpl = options.fetch ?? fetch;
2240
+ }
2241
+ options;
2242
+ name = "vertex_anthropic";
2243
+ fetchImpl;
2244
+ resolveProjectOrThrow() {
2245
+ const projectId = this.options.projectId ?? resolveVertexProjectId();
2246
+ if (projectId !== void 0) return projectId;
2247
+ throw new chunkA44COQJJ_cjs.ConfigurationError(
2248
+ "Vertex requires a project id. Set GOOGLE_CLOUD_PROJECT env var or run `gcloud config set project <id>`.",
2249
+ { code: "auth_failed" }
2250
+ );
2251
+ }
2252
+ async resolveTokenOrThrow() {
2253
+ const fromOpts = this.options.apiKey;
2254
+ if (fromOpts !== void 0 && fromOpts.length > 0) return fromOpts;
2255
+ const fromAdc = await resolveVertexAccessToken();
2256
+ if (fromAdc !== void 0 && fromAdc.length > 0) return fromAdc;
2257
+ throw new chunkA44COQJJ_cjs.ConfigurationError(
2258
+ "Vertex could not resolve an access token. Run `gcloud auth application-default login` or set GOOGLE_APPLICATION_CREDENTIALS to a service-account JSON path.",
2259
+ { code: "auth_failed" }
2260
+ );
2261
+ }
2262
+ async *stream(request, signal) {
2263
+ const projectId = this.resolveProjectOrThrow();
2264
+ const location = this.options.location ?? resolveVertexLocation();
2265
+ const accessToken = await this.resolveTokenOrThrow();
2266
+ const baseUrl = chunkD42XHI4O_cjs.resolveVertexBaseUrl({ projectId, location, modelDialect: "anthropic" });
2267
+ const bareModel = chunkD42XHI4O_cjs.stripVertexPrefix(request.model);
2268
+ const endpoint = `/models/${encodeURIComponent(bareModel)}:rawPredict`;
2269
+ const url = `${baseUrl}${endpoint}`;
2270
+ const response = await postAnthropicRequest({
2271
+ fetchImpl: this.fetchImpl,
2272
+ url,
2273
+ token: accessToken,
2274
+ body: buildVertexAnthropicBody(request),
2275
+ signal
2276
+ });
2277
+ const consumed = await handleAnthropicResponse({
2278
+ response,
2279
+ endpoint,
2280
+ errorMapper: mapVertexError
2281
+ });
2282
+ if (consumed.text.length > 0) yield { type: "text_delta", text: consumed.text };
2283
+ return makeLlmFinish(consumed);
2284
+ }
2285
+ };
2286
+ function buildVertexAnthropicBody(request) {
2287
+ return {
2288
+ anthropic_version: "vertex-2023-10-16",
2289
+ ...buildAnthropicCommonBody(request)
2290
+ };
2291
+ }
2292
+
2293
+ // src/internal/llm/vertex-gemini.ts
2294
+ var VertexGeminiClient = class {
2295
+ constructor(options) {
2296
+ this.options = options;
2297
+ }
2298
+ options;
2299
+ name = "vertex_gemini";
2300
+ async *stream(request, signal) {
2301
+ const projectId = this.options.projectId ?? resolveVertexProjectId();
2302
+ if (projectId === void 0) {
2303
+ throw new chunkA44COQJJ_cjs.ConfigurationError(
2304
+ "Vertex requires a project id. Set GOOGLE_CLOUD_PROJECT env var or run `gcloud config set project <id>`.",
2305
+ { code: "auth_failed" }
2306
+ );
2307
+ }
2308
+ const location = this.options.location ?? resolveVertexLocation();
2309
+ const accessToken = this.options.apiKey !== void 0 && this.options.apiKey.length > 0 ? this.options.apiKey : await resolveVertexAccessToken();
2310
+ if (accessToken === void 0 || accessToken.length === 0) {
2311
+ throw new chunkA44COQJJ_cjs.ConfigurationError(
2312
+ "Vertex could not resolve an access token. Run `gcloud auth application-default login` or set GOOGLE_APPLICATION_CREDENTIALS to a service-account JSON path.",
2313
+ { code: "auth_failed" }
2314
+ );
2315
+ }
2316
+ const baseUrl = chunkD42XHI4O_cjs.resolveVertexBaseUrl({ projectId, location, modelDialect: "gemini" });
2317
+ const url = `${baseUrl}/chat/completions`;
2318
+ const innerFetch = this.options.fetch ?? fetch;
2319
+ const rewriteFetch = (input, init) => {
2320
+ const requested = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
2321
+ const targetUrl = requested.endsWith("/v1/chat/completions") ? url : requested;
2322
+ return innerFetch(targetUrl, init);
2323
+ };
2324
+ const inner = new OpenAIClient({
2325
+ apiKey: accessToken,
2326
+ baseUrl: "https://_vertex_placeholder",
2327
+ providerName: "vertex",
2328
+ fetch: rewriteFetch
2329
+ });
2330
+ return yield* inner.stream(request, signal);
2331
+ }
2332
+ };
2333
+
2334
+ // src/internal/llm/vertex-router.ts
2335
+ var VertexRouterClient = class {
2336
+ constructor(options) {
2337
+ this.options = options;
2338
+ }
2339
+ options;
2340
+ name = "vertex";
2341
+ async *stream(request, signal) {
2342
+ const dialect = chunkD42XHI4O_cjs.inferModelDialect(request.model);
2343
+ if (dialect === "anthropic") {
2344
+ const inner2 = new VertexAnthropicClient(this.options);
2345
+ return yield* inner2.stream(request, signal);
2346
+ }
2347
+ const inner = new VertexGeminiClient(this.options);
2348
+ return yield* inner.stream(request, signal);
2349
+ }
2350
+ };
2351
+
2352
+ // src/internal/llm/router.ts
2353
+ function resolveProviderChain(options) {
2354
+ chunkD42XHI4O_cjs.registerBuiltins();
2355
+ return buildChain(options);
2356
+ }
2357
+ function buildChain(options) {
2358
+ warnUnknownProvidersInApiKeys(options.apiKeys);
2359
+ const seen = /* @__PURE__ */ new Set();
2360
+ const clients = [];
2361
+ const addClient = (name) => {
2362
+ const lowered = name.toLowerCase();
2363
+ if (seen.has(lowered)) return;
2364
+ seen.add(lowered);
2365
+ const client = buildClient(lowered, options);
2366
+ if (client !== void 0) clients.push(maybeWrapWithFaultInjection(client));
2367
+ };
2368
+ addClient(options.primary);
2369
+ for (const fallback of options.fallback ?? []) addClient(fallback);
2370
+ if (clients.length === 0) {
2371
+ throw new chunkA44COQJJ_cjs.ConfigurationError(
2372
+ `No provider client could be resolved (primary=${options.primary}). Set ANTHROPIC_API_KEY or OPENAI_API_KEY / OPENROUTER_API_KEY.`,
2373
+ { code: "provider_unresolved" }
2374
+ );
2375
+ }
2376
+ return clients;
2377
+ }
2378
+ function buildClient(name, routerOptions) {
2379
+ const baseProfile = chunkD42XHI4O_cjs.getProviderProfile(name);
2380
+ if (baseProfile === void 0) return void 0;
2381
+ const profile = routerOptions.extractToolCallsFromContent === true && baseProfile.extractToolCallsFromContent !== true ? { ...baseProfile, extractToolCallsFromContent: true } : baseProfile;
2382
+ const resilience = routerOptions.onRateLimit !== void 0 ? { onRateLimit: routerOptions.onRateLimit } : {};
2383
+ const ambient = chunkLUSXDZPV_cjs.currentCredentialPool(name);
2384
+ if (ambient !== void 0) {
2385
+ return new PoolAwareLlmClient(
2386
+ ambient,
2387
+ (apiKey) => selectTransport(profile, apiKey),
2388
+ void 0,
2389
+ resilience
2390
+ );
2391
+ }
2392
+ const poolKeys = filterPoolKeys(routerOptions.apiKeys?.[name]);
2393
+ const noAuthOverride = maybeBuildNoAuthTransport(profile, poolKeys);
2394
+ if (noAuthOverride !== void 0) return noAuthOverride;
2395
+ return buildPoolOrSingle({ name, profile, poolKeys, routerOptions });
2396
+ }
2397
+ function maybeBuildNoAuthTransport(profile, poolKeys) {
2398
+ if (profile.authType !== "none" || poolKeys === void 0 || poolKeys.length === 0) {
2399
+ return void 0;
2400
+ }
2401
+ warnNoAuthApiKeysIgnoredOnce(profile.name);
2402
+ const sentinel = sentinelForNoAuth(profile);
2403
+ if (sentinel === void 0) return void 0;
2404
+ return selectTransport(profile, sentinel);
2405
+ }
2406
+ function buildPoolOrSingle(args) {
2407
+ const { name, profile, poolKeys, routerOptions } = args;
2408
+ if (poolKeys !== void 0 && poolKeys.length >= 2) {
2409
+ const strategy = routerOptions.credentialPoolStrategy?.[name] ?? "fill_first";
2410
+ const entries = poolKeys.map(
2411
+ (accessToken, priority) => chunkLUSXDZPV_cjs.newPooledCredential({ provider: name, accessToken, priority, source: "manual" })
2412
+ );
2413
+ const pool = new chunkLUSXDZPV_cjs.CredentialPool(name, entries, strategy);
2414
+ const resilience = routerOptions.onRateLimit !== void 0 ? { onRateLimit: routerOptions.onRateLimit } : {};
2415
+ return new PoolAwareLlmClient(
2416
+ pool,
2417
+ (apiKey2) => selectTransport(profile, apiKey2),
2418
+ void 0,
2419
+ resilience
2420
+ );
2421
+ }
2422
+ const apiKey = poolKeys?.[0] ?? resolveApiKey(profile.envVars) ?? sentinelForNoAuth(profile) ?? sentinelForLazyAuth(profile);
2423
+ if (apiKey === void 0) return void 0;
2424
+ return selectTransport(profile, apiKey);
2425
+ }
2426
+ function resolveBaseUrlEnvOverride(providerName) {
2427
+ switch (providerName) {
2428
+ case "openai":
2429
+ return process.env.OPENAI_API_BASE_URL;
2430
+ case "openrouter":
2431
+ return process.env.OPENROUTER_API_BASE_URL;
2432
+ case "ollama":
2433
+ return process.env.OLLAMA_HOST;
2434
+ case "lmstudio":
2435
+ return process.env.LMSTUDIO_HOST;
2436
+ case "llamacpp":
2437
+ return process.env.LLAMACPP_HOST;
2438
+ default:
2439
+ return void 0;
2440
+ }
2441
+ }
2442
+ var warnedNoAuthApiKeys = /* @__PURE__ */ new Set();
2443
+ function warnNoAuthApiKeysIgnoredOnce(provider) {
2444
+ if (warnedNoAuthApiKeys.has(provider)) return;
2445
+ warnedNoAuthApiKeys.add(provider);
2446
+ process.stderr.write(
2447
+ `[theokit-sdk] provider "${provider}" has authType: "none" \u2014 apiKeys ignored (no auth required for local runtime).
2448
+ `
2449
+ );
2450
+ }
2451
+ function sentinelForNoAuth(profile) {
2452
+ return profile.authType === "none" ? profile.name : void 0;
2453
+ }
2454
+ function sentinelForLazyAuth(profile) {
2455
+ if (profile.authType === "aws_bearer") return "__bedrock_lazy_token__";
2456
+ if (profile.authType === "gcp_oauth") return "__vertex_lazy_token__";
2457
+ if (profile.authType === "oauth_device_code" || profile.authType === "oauth_external") {
2458
+ return "__oauth_lazy_token__";
2459
+ }
2460
+ return void 0;
2461
+ }
2462
+ function filterPoolKeys(keys) {
2463
+ if (keys === void 0) return void 0;
2464
+ const cleaned = keys.filter((k) => typeof k === "string" && k.length > 0);
2465
+ return cleaned.length === 0 ? void 0 : cleaned;
2466
+ }
2467
+ var warnedProviders = /* @__PURE__ */ new Set();
2468
+ function warnUnknownProvidersInApiKeys(apiKeys) {
2469
+ if (apiKeys === void 0) return;
2470
+ for (const name of Object.keys(apiKeys)) {
2471
+ if (warnedProviders.has(name)) continue;
2472
+ const profile = chunkD42XHI4O_cjs.getProviderProfile(name);
2473
+ if (profile === void 0) {
2474
+ warnedProviders.add(name);
2475
+ process.stderr.write(
2476
+ `[theokit-sdk] credential-pool: unknown provider "${name}" in apiKeys (no profile registered)
2477
+ `
2478
+ );
2479
+ }
2480
+ }
2481
+ }
2482
+ function resolveApiKey(envVars) {
2483
+ for (const v of envVars) {
2484
+ const value = process.env[v];
2485
+ if (value !== void 0 && value.length > 0) return value;
2486
+ }
2487
+ return void 0;
2488
+ }
2489
+ function selectTransport(profile, apiKey) {
2490
+ const applyTransform = () => {
2491
+ if (profile.transform === void 0) return {};
2492
+ const ctx = { apiKey };
2493
+ return { fetch: profile.transform.fetch?.(ctx), headers: profile.transform.headers?.(ctx) };
2494
+ };
2495
+ const comTransform = (opts, criar) => {
2496
+ const t = applyTransform();
2497
+ assertOAuthResolved(t);
2498
+ if (t.fetch !== void 0) opts.fetch = t.fetch;
2499
+ const merged = profile.extraHeaders !== void 0 || t.headers !== void 0 ? { ...profile.extraHeaders, ...t.headers } : void 0;
2500
+ if (merged !== void 0) opts.extraHeaders = merged;
2501
+ return criar(opts);
2502
+ };
2503
+ const assertOAuthResolved = (t) => {
2504
+ if (apiKey !== "__oauth_lazy_token__") return;
2505
+ const auth = t.headers?.authorization ?? t.headers?.Authorization;
2506
+ if (t.fetch === void 0 && auth === void 0) {
2507
+ throw new chunkA44COQJJ_cjs.ConfigurationError(
2508
+ `provider "${profile.name}" uses OAuth (authType: ${profile.authType}) but no credential was resolved. Register a ProviderProfile.transform whose fetch (or headers.authorization) supplies the bearer \u2014 typically via resolveCredential() from "@theokit/sdk/auth".`
2509
+ );
2510
+ }
2511
+ };
2512
+ if (profile.apiMode === "chat_completions") {
2513
+ if (profile.name === "ollama") {
2514
+ const ollamaBase = process.env.OLLAMA_HOST ?? profile.baseUrl;
2515
+ return new OllamaNativeClient({ apiKey, baseUrl: ollamaBase });
2516
+ }
2517
+ const opts = { apiKey };
2518
+ opts.baseUrl = profile.baseUrl;
2519
+ opts.providerName = profile.name;
2520
+ if (profile.extractToolCallsFromContent === true) {
2521
+ opts.extractToolCallsFromContent = true;
2522
+ }
2523
+ if (profile.chatCompletionsPath !== void 0) {
2524
+ opts.chatCompletionsPath = profile.chatCompletionsPath;
2525
+ }
2526
+ if (profile.name === "openai" && process.env.OPENAI_ORGANIZATION !== void 0) {
2527
+ opts.organization = process.env.OPENAI_ORGANIZATION;
2528
+ }
2529
+ const envOverride = resolveBaseUrlEnvOverride(profile.name);
2530
+ if (envOverride !== void 0) opts.baseUrl = envOverride;
2531
+ return comTransform(opts, (o) => new OpenAIClient(o));
2532
+ }
2533
+ if (profile.apiMode === "anthropic_messages") {
2534
+ if (profile.name === "vertex") {
2535
+ const realKey = apiKey === "__vertex_lazy_token__" ? void 0 : apiKey;
2536
+ return new VertexRouterClient(realKey !== void 0 ? { apiKey: realKey } : {});
2537
+ }
2538
+ const opts = { apiKey };
2539
+ opts.baseUrl = process.env.ANTHROPIC_API_BASE_URL ?? profile.baseUrl;
2540
+ return comTransform(opts, (o) => new AnthropicClient(o));
2541
+ }
2542
+ if (profile.apiMode === "bedrock_anthropic") {
2543
+ const realKey = apiKey === "__bedrock_lazy_token__" ? void 0 : apiKey;
2544
+ return new BedrockAnthropicClient(realKey !== void 0 ? { apiKey: realKey } : {});
2545
+ }
2546
+ if (profile.apiMode === "responses_api") {
2547
+ const t = applyTransform();
2548
+ assertOAuthResolved(t);
2549
+ const mergedHeaders = profile.extraHeaders !== void 0 || t.headers !== void 0 ? { ...profile.extraHeaders, ...t.headers } : void 0;
2550
+ return new ResponsesApiClient({
2551
+ apiKey,
2552
+ ...profile.baseUrl !== void 0 ? { baseUrl: profile.baseUrl } : {},
2553
+ ...mergedHeaders !== void 0 ? { extraHeaders: mergedHeaders } : {},
2554
+ ...t.fetch !== void 0 ? { fetch: t.fetch } : {},
2555
+ providerName: profile.name
2556
+ });
2557
+ }
2558
+ throw new chunkA44COQJJ_cjs.ConfigurationError(
2559
+ `Provider "${profile.name}" requires apiMode "${profile.apiMode}" but no transport is registered. Install a third-party transport plugin (@theokit-transport-${profile.apiMode}) or use a provider with apiMode "chat_completions" or "anthropic_messages".`,
2560
+ { code: "transport_unavailable" }
2561
+ );
2562
+ }
2563
+
2564
+ // src/internal/local-agent/real-local-run-provider.ts
2565
+ function inferProviderFromApiKey(apiKey) {
2566
+ if (apiKey === void 0 || apiKey.length === 0) return void 0;
2567
+ const byPrefix = [
2568
+ { provider: "openrouter", prefix: "sk-or-" },
2569
+ { provider: "anthropic", prefix: "sk-ant-" },
2570
+ { provider: "openai", prefix: "sk-" }
2571
+ ];
2572
+ for (const { provider, prefix } of byPrefix) {
2573
+ if (apiKey.startsWith(prefix) && chunkD42XHI4O_cjs.getProviderProfile(provider) !== void 0) {
2574
+ return provider;
2575
+ }
2576
+ }
2577
+ return void 0;
2578
+ }
2579
+ function detectPrimaryProvider() {
2580
+ if (process.env.ANTHROPIC_API_KEY !== void 0 && process.env.ANTHROPIC_API_KEY.length > 0) {
2581
+ return "anthropic";
2582
+ }
2583
+ if (process.env.OPENAI_API_KEY !== void 0 && process.env.OPENAI_API_KEY.length > 0) {
2584
+ return "openai";
2585
+ }
2586
+ if (process.env.OPENROUTER_API_KEY !== void 0 && process.env.OPENROUTER_API_KEY.length > 0) {
2587
+ return "openrouter";
2588
+ }
2589
+ return "openai";
2590
+ }
2591
+
2592
+ // src/internal/runtime/compression/compression-model-registry.ts
2593
+ var EXACT_REGISTRY = /* @__PURE__ */ new Map([
2594
+ // OpenAI family
2595
+ ["openai/gpt-4o", "openai/gpt-4o-mini"],
2596
+ ["openai/gpt-4-turbo", "openai/gpt-4o-mini"],
2597
+ ["openai/gpt-4", "openai/gpt-4o-mini"],
2598
+ ["openai/o1-preview", "openai/gpt-4o-mini"],
2599
+ ["openai/o1", "openai/gpt-4o-mini"],
2600
+ ["openai/o3", "openai/gpt-4o-mini"],
2601
+ ["openai/o3-mini", "openai/gpt-4o-mini"],
2602
+ // Anthropic family
2603
+ ["anthropic/claude-opus-4", "anthropic/claude-3-5-haiku-latest"],
2604
+ ["anthropic/claude-sonnet-4", "anthropic/claude-3-5-haiku-latest"],
2605
+ ["anthropic/claude-3-5-sonnet", "anthropic/claude-3-5-haiku-latest"],
2606
+ ["anthropic/claude-3-5-sonnet-latest", "anthropic/claude-3-5-haiku-latest"],
2607
+ ["anthropic/claude-3-opus", "anthropic/claude-3-haiku"],
2608
+ ["anthropic/claude-3-sonnet", "anthropic/claude-3-haiku"],
2609
+ // Vertex (Gemini + Anthropic-on-Vertex)
2610
+ ["vertex/gemini-1.5-pro", "vertex/gemini-1.5-flash"],
2611
+ ["vertex/gemini-2.0-pro", "vertex/gemini-1.5-flash"],
2612
+ ["vertex/claude-3-5-sonnet", "vertex/claude-3-5-haiku"],
2613
+ ["vertex/claude-3-opus", "vertex/claude-3-haiku"],
2614
+ // OpenRouter (preserve openrouter prefix, swap tier within same vendor)
2615
+ ["openrouter/openai/gpt-4o", "openrouter/openai/gpt-4o-mini"],
2616
+ ["openrouter/openai/gpt-4-turbo", "openrouter/openai/gpt-4o-mini"],
2617
+ ["openrouter/anthropic/claude-3-5-sonnet", "openrouter/anthropic/claude-3-5-haiku"],
2618
+ ["openrouter/anthropic/claude-opus-4", "openrouter/anthropic/claude-3-5-haiku"]
2619
+ ]);
2620
+ var WILDCARD_REGISTRY = [
2621
+ // Bedrock Anthropic: us.anthropic.claude-sonnet-* → us.anthropic.claude-3-haiku-*
2622
+ ["bedrock/anthropic.claude-sonnet*", "bedrock/anthropic.claude-3-haiku*"],
2623
+ ["bedrock/anthropic.claude-opus*", "bedrock/anthropic.claude-3-haiku*"],
2624
+ ["bedrock/anthropic.claude-3-5-sonnet*", "bedrock/anthropic.claude-3-5-haiku*"]
2625
+ ];
2626
+ var NO_AUTH_PROVIDERS = /* @__PURE__ */ new Set(["ollama", "lmstudio", "llamacpp"]);
2627
+ var CompressionModelUnresolvedError = class extends Error {
2628
+ name = "CompressionModelUnresolvedError";
2629
+ agentModel;
2630
+ constructor(agentModel) {
2631
+ super(
2632
+ `Could not resolve a same-family-cheaper-tier compression model for "${agentModel}". Provide Agent.create({compression: {model: "<your-cheaper-model>"}}) OR add "${agentModel}" to the compression-model-registry (see ADR D440).`
2633
+ );
2634
+ this.agentModel = agentModel;
2635
+ }
2636
+ };
2637
+ function resolveCompressionModel(agentModel) {
2638
+ const exact = EXACT_REGISTRY.get(agentModel);
2639
+ if (exact !== void 0) return exact;
2640
+ const wildcard = matchWildcard(agentModel);
2641
+ if (wildcard !== null) return wildcard;
2642
+ if (isNoAuthProvider(agentModel)) return agentModel;
2643
+ throw new CompressionModelUnresolvedError(agentModel);
2644
+ }
2645
+ function matchWildcard(agentModel) {
2646
+ for (const [pattern, replacement] of WILDCARD_REGISTRY) {
2647
+ const prefix = pattern.endsWith("*") ? pattern.slice(0, -1) : pattern;
2648
+ if (!agentModel.startsWith(prefix)) continue;
2649
+ const suffix = agentModel.slice(prefix.length);
2650
+ const replPrefix = replacement.endsWith("*") ? replacement.slice(0, -1) : replacement;
2651
+ return `${replPrefix}${suffix}`;
2652
+ }
2653
+ return null;
2654
+ }
2655
+ function isNoAuthProvider(agentModel) {
2656
+ const slashIdx = agentModel.indexOf("/");
2657
+ if (slashIdx <= 0) return false;
2658
+ return NO_AUTH_PROVIDERS.has(agentModel.slice(0, slashIdx));
2659
+ }
2660
+
2661
+ // src/internal/runtime/compression/compression-summarizer.ts
2662
+ var CompressionFailedError = class extends Error {
2663
+ name = "CompressionFailedError";
2664
+ };
2665
+ function buildCompressionPrompt(messages) {
2666
+ const formatted = messages.map((m) => `[${m.role}]: ${m.content}`).join("\n\n");
2667
+ return `Summarize the following ${messages.length} conversation messages into a concise summary that preserves ALL facts, decisions, user preferences, and context needed for the conversation to continue naturally. The summary will replace these messages in the context window. Be thorough but concise.
2668
+
2669
+ --- CONVERSATION TO SUMMARIZE ---
2670
+ ${formatted}
2671
+ --- END ---`;
2672
+ }
2673
+ var COMPRESSION_SYSTEM = "You are a conversation summarizer. Produce a concise factual summary. Preserve all decisions, preferences, code snippets, and action items. Do not add commentary or opinions. Output ONLY the summary text.";
2674
+ async function compressConversationWindow(opts) {
2675
+ const userPrompt = buildCompressionPrompt(opts.messages);
2676
+ let summary;
2677
+ try {
2678
+ summary = await opts.callLlm(opts.model, COMPRESSION_SYSTEM, userPrompt);
2679
+ } catch (cause) {
2680
+ throw new CompressionFailedError(
2681
+ `Compression LLM call failed: ${cause instanceof Error ? cause.message : String(cause)}`,
2682
+ { cause: cause instanceof Error ? cause : void 0 }
2683
+ );
2684
+ }
2685
+ if (!summary || summary.trim().length === 0) {
2686
+ throw new CompressionFailedError(
2687
+ "Compression LLM returned empty summary \u2014 reduction ineffective."
2688
+ );
2689
+ }
2690
+ return {
2691
+ role: "system",
2692
+ content: `[Compressed conversation summary]: ${summary.trim()}`
2693
+ };
2694
+ }
2695
+
2696
+ // src/internal/session/compact-session.ts
2697
+ var COMPACT_SUMMARY_MARKER = "[[theokit:compact-summary]]";
2698
+ var COMPACT_USER_MESSAGE_MAX_TOKENS = 2e4;
2699
+ function isCompactSummary(content) {
2700
+ return content.startsWith(COMPACT_SUMMARY_MARKER) || content.startsWith("[[theokit:goal-continuation]]");
2701
+ }
2702
+ function plainText(content) {
2703
+ if (typeof content === "string") return content;
2704
+ if (!Array.isArray(content)) return void 0;
2705
+ const texts = content.filter(
2706
+ (p) => p !== null && typeof p === "object" && p.type === "text" && typeof p.text === "string"
2707
+ ).map((p) => p.text);
2708
+ return texts.length > 0 ? texts.join("\n") : void 0;
2709
+ }
2710
+ async function compactSessionTranscript(opts) {
2711
+ const prior = await opts.store.readRecords(opts.loc.agentId);
2712
+ const history = chunk4SXHEZIV_cjs.reconstructMessages(prior);
2713
+ const compressible = [];
2714
+ for (const m of history) {
2715
+ const text = plainText(m.content);
2716
+ if (text !== void 0 && (m.role === "user" || m.role === "assistant" || m.role === "system")) {
2717
+ compressible.push({ role: m.role, content: text });
2718
+ }
2719
+ }
2720
+ const preTokens = chunkEVADEGM7_cjs.estimateTokens(compressible.map((m) => m.content).join("\n"));
2721
+ const summaryBody = await opts.summarize(compressible);
2722
+ const preserved = [];
2723
+ let budget = 0;
2724
+ for (let i = compressible.length - 1; i >= 0; i--) {
2725
+ const m = compressible[i];
2726
+ if (m === void 0 || m.role !== "user" || isCompactSummary(m.content)) continue;
2727
+ const cost = chunkEVADEGM7_cjs.estimateTokens(m.content);
2728
+ if (budget + cost > COMPACT_USER_MESSAGE_MAX_TOKENS) {
2729
+ const remaining = COMPACT_USER_MESSAGE_MAX_TOKENS - budget;
2730
+ if (remaining > 50) {
2731
+ preserved.unshift(`${m.content.slice(0, remaining * 4)}
2732
+ [...truncated for compaction...]`);
2733
+ }
2734
+ break;
2735
+ }
2736
+ budget += cost;
2737
+ preserved.unshift(m.content);
2738
+ }
2739
+ const summary = `${COMPACT_SUMMARY_MARKER}
2740
+ ${summaryBody}`;
2741
+ const transcript = chunk4SXHEZIV_cjs.SessionTranscript.fromRecords(prior, {
2742
+ cwd: opts.loc.cwd,
2743
+ sessionId: opts.sessionId,
2744
+ model: opts.loc.model ?? "unknown"
2745
+ });
2746
+ transcript.appendCompactBoundary({ preTokens, trigger: opts.trigger });
2747
+ for (const text of preserved) transcript.appendUserTurn(text);
2748
+ transcript.appendUserTurn(summary);
2749
+ const delta = transcript.records().slice(prior.length);
2750
+ await opts.store.appendRecords(opts.loc.agentId, delta);
2751
+ chunkIT3PWBW4_cjs.invalidateSessionCache(opts.loc.cwd, opts.loc.agentId);
2752
+ const postTokens = chunkEVADEGM7_cjs.estimateTokens([...preserved, summary].join("\n"));
2753
+ return { preTokens, postTokens };
2754
+ }
2755
+ function resolveSummarizerRoute(opts) {
2756
+ const provider = opts.keyProvider ?? (opts.prefixHasProfile && opts.modelPrefix !== void 0 ? opts.modelPrefix : opts.envProvider);
2757
+ return { provider, fullSlug: provider !== opts.modelPrefix };
2758
+ }
2759
+ function buildDefaultSummarizer(opts) {
2760
+ return async (messages) => {
2761
+ chunkD42XHI4O_cjs.registerBuiltins();
2762
+ const modelPrefix = opts.agentModel.includes("/") ? opts.agentModel.slice(0, opts.agentModel.indexOf("/")) : void 0;
2763
+ const prefixProfile = modelPrefix !== void 0 ? chunkD42XHI4O_cjs.getProviderProfile(modelPrefix) : void 0;
2764
+ const prefixUsable = prefixProfile !== void 0 && (prefixProfile.authType !== "api_key" || prefixProfile.envVars.some((v) => (process.env[v] ?? "").length > 0));
2765
+ const route = resolveSummarizerRoute({
2766
+ keyProvider: inferProviderFromApiKey(opts.apiKey),
2767
+ modelPrefix,
2768
+ prefixHasProfile: prefixUsable,
2769
+ envProvider: detectPrimaryProvider()
2770
+ });
2771
+ const provider = route.provider;
2772
+ let model;
2773
+ if (route.fullSlug) {
2774
+ model = opts.agentModel;
2775
+ } else {
2776
+ try {
2777
+ model = resolveCompressionModel(opts.agentModel);
2778
+ } catch {
2779
+ model = opts.agentModel;
2780
+ }
2781
+ }
2782
+ const callLlm = async (m, system, user) => {
2783
+ const chain = resolveProviderChain({
2784
+ primary: provider,
2785
+ ...opts.apiKey !== void 0 ? { apiKeys: { [provider]: [opts.apiKey] } } : {}
2786
+ });
2787
+ const client = chain[0];
2788
+ if (client === void 0) throw new Error(`no LLM client for provider "${provider}"`);
2789
+ const controller = new AbortController();
2790
+ let text = "";
2791
+ const stream = client.stream(
2792
+ { model: m, system, messages: [{ role: "user", content: [{ type: "text", text: user }] }] },
2793
+ controller.signal
2794
+ );
2795
+ for (; ; ) {
2796
+ const step = await stream.next();
2797
+ if (step.done === true) break;
2798
+ if (step.value.type === "text_delta") text += step.value.text;
2799
+ if (step.value.type === "error") throw new Error(step.value.message);
2800
+ }
2801
+ return text;
2802
+ };
2803
+ const summary = await compressConversationWindow({ messages: [...messages], model, callLlm });
2804
+ return summary.content;
2805
+ };
2806
+ }
2807
+ function shouldAutoCompact(opts) {
2808
+ if (opts.usageTotal === void 0 || opts.contextWindow === void 0) return false;
2809
+ if (opts.usageTotal <= 0 || opts.contextWindow <= 0) return false;
2810
+ return opts.usageTotal >= Math.floor(opts.contextWindow * 9 / 10);
2811
+ }
2812
+ var autoCompactAttempts = (() => {
2813
+ const g = globalThis;
2814
+ const sym = /* @__PURE__ */ Symbol.for("theokit-sdk.session.auto-compact-attempts");
2815
+ if (g[sym] === void 0) g[sym] = /* @__PURE__ */ new Map();
2816
+ return g[sym];
2817
+ })();
2818
+ async function autoCompactIfNeeded(opts) {
2819
+ if (!shouldAutoCompact(opts)) return false;
2820
+ const key = `${opts.loc.cwd}::${opts.loc.agentId}`;
2821
+ if (autoCompactAttempts.get(key) === opts.turnCount) return false;
2822
+ autoCompactAttempts.set(key, opts.turnCount);
2823
+ try {
2824
+ await compactSessionTranscript({
2825
+ store: opts.store,
2826
+ loc: opts.loc,
2827
+ sessionId: opts.sessionId,
2828
+ trigger: "auto",
2829
+ summarize: opts.summarize
2830
+ });
2831
+ return true;
2832
+ } catch (cause) {
2833
+ const msg = cause instanceof Error ? cause.message : String(cause);
2834
+ process.stderr.write(
2835
+ `[theokit-sdk] auto-compaction failed (left transcript untouched): ${msg}
2836
+ `
2837
+ );
2838
+ return false;
2839
+ }
2840
+ }
2841
+
2842
+ exports.COMPACT_SUMMARY_MARKER = COMPACT_SUMMARY_MARKER;
2843
+ exports.COMPACT_USER_MESSAGE_MAX_TOKENS = COMPACT_USER_MESSAGE_MAX_TOKENS;
2844
+ exports.CircuitBreaker = CircuitBreaker;
2845
+ exports.autoCompactIfNeeded = autoCompactIfNeeded;
2846
+ exports.buildDefaultSummarizer = buildDefaultSummarizer;
2847
+ exports.compactSessionTranscript = compactSessionTranscript;
2848
+ exports.detectPrimaryProvider = detectPrimaryProvider;
2849
+ exports.discoverProviderPlugins = discoverProviderPlugins;
2850
+ exports.inferProviderFromApiKey = inferProviderFromApiKey;
2851
+ exports.isCompactSummary = isCompactSummary;
2852
+ exports.mapOllamaHttpError = mapOllamaHttpError;
2853
+ exports.mapOllamaTransportError = mapOllamaTransportError;
2854
+ exports.mapOpenAICompatibleError = mapOpenAICompatibleError;
2855
+ exports.parseSseStream = parseSseStream;
2856
+ exports.relayStream = relayStream;
2857
+ exports.renderToolResultContentText = renderToolResultContentText;
2858
+ exports.resolveProviderChain = resolveProviderChain;
2859
+ exports.resolveSummarizerRoute = resolveSummarizerRoute;
2860
+ exports.shouldAutoCompact = shouldAutoCompact;
2861
+ exports.tryFirstEvent = tryFirstEvent;
2862
+ //# sourceMappingURL=chunk-2MF3IE2D.cjs.map
2863
+ //# sourceMappingURL=chunk-2MF3IE2D.cjs.map