@graphrefly/graphrefly 0.44.0 → 0.46.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 (720) hide show
  1. package/README.md +22 -19
  2. package/dist/_internal-B23BagFd.d.cts +33 -0
  3. package/dist/_internal-B23BagFd.d.ts +33 -0
  4. package/dist/adaptive-rate-limiter-Dch_xYIi.d.cts +111 -0
  5. package/dist/adaptive-rate-limiter-Dch_xYIi.d.ts +111 -0
  6. package/dist/agents-C0Ji9ldU.d.cts +629 -0
  7. package/dist/agents-C9zexT7I.d.ts +629 -0
  8. package/dist/audit-BAXb3VOg.d.ts +246 -0
  9. package/dist/audit-C_bPfkqS.d.cts +246 -0
  10. package/dist/backoff-7KIK3WQW.js +24 -0
  11. package/dist/backoff-7KIK3WQW.js.map +1 -0
  12. package/dist/backoff-Bnb9OoPh.d.cts +6 -0
  13. package/dist/backoff-Bnb9OoPh.d.ts +6 -0
  14. package/dist/base/composition/index.cjs +811 -0
  15. package/dist/base/composition/index.cjs.map +1 -0
  16. package/dist/base/composition/index.d.cts +469 -0
  17. package/dist/base/composition/index.d.ts +469 -0
  18. package/dist/base/composition/index.js +40 -0
  19. package/dist/base/composition/index.js.map +1 -0
  20. package/dist/base/index.cjs +6336 -0
  21. package/dist/base/index.cjs.map +1 -0
  22. package/dist/base/index.d.cts +22 -0
  23. package/dist/base/index.d.ts +22 -0
  24. package/dist/base/index.js +259 -0
  25. package/dist/base/index.js.map +1 -0
  26. package/dist/base/io/index.cjs +3270 -0
  27. package/dist/base/io/index.cjs.map +1 -0
  28. package/dist/base/io/index.d.cts +2245 -0
  29. package/dist/base/io/index.d.ts +2245 -0
  30. package/dist/base/io/index.js +117 -0
  31. package/dist/base/io/index.js.map +1 -0
  32. package/dist/base/meta/index.cjs +43 -0
  33. package/dist/base/meta/index.cjs.map +1 -0
  34. package/dist/base/meta/index.d.cts +45 -0
  35. package/dist/base/meta/index.d.ts +45 -0
  36. package/dist/base/meta/index.js +13 -0
  37. package/dist/base/meta/index.js.map +1 -0
  38. package/dist/base/mutation/index.cjs +200 -0
  39. package/dist/base/mutation/index.cjs.map +1 -0
  40. package/dist/base/mutation/index.d.cts +177 -0
  41. package/dist/base/mutation/index.d.ts +177 -0
  42. package/dist/base/mutation/index.js +22 -0
  43. package/dist/base/mutation/index.js.map +1 -0
  44. package/dist/base/render/index.cjs +1120 -0
  45. package/dist/base/render/index.cjs.map +1 -0
  46. package/dist/{extra/render/index.d.ts → base/render/index.d.cts} +75 -31
  47. package/dist/{extra/render/index.d.cts → base/render/index.d.ts} +75 -31
  48. package/dist/base/render/index.js +24 -0
  49. package/dist/base/render/index.js.map +1 -0
  50. package/dist/base/sources/browser/index.cjs +172 -0
  51. package/dist/base/sources/browser/index.cjs.map +1 -0
  52. package/dist/base/sources/browser/index.d.cts +84 -0
  53. package/dist/base/sources/browser/index.d.ts +84 -0
  54. package/dist/base/sources/browser/index.js +151 -0
  55. package/dist/base/sources/browser/index.js.map +1 -0
  56. package/dist/base/sources/event/index.cjs +98 -0
  57. package/dist/base/sources/event/index.cjs.map +1 -0
  58. package/dist/base/sources/event/index.d.cts +91 -0
  59. package/dist/base/sources/event/index.d.ts +91 -0
  60. package/dist/base/sources/event/index.js +13 -0
  61. package/dist/base/sources/event/index.js.map +1 -0
  62. package/dist/base/sources/index.cjs +755 -0
  63. package/dist/base/sources/index.cjs.map +1 -0
  64. package/dist/{extra/sources.d.ts → base/sources/index.d.cts} +74 -301
  65. package/dist/{extra/sources.d.cts → base/sources/index.d.ts} +74 -301
  66. package/dist/base/sources/index.js +42 -0
  67. package/dist/base/sources/index.js.map +1 -0
  68. package/dist/base/sources/node/index.cjs +320 -0
  69. package/dist/base/sources/node/index.cjs.map +1 -0
  70. package/dist/{extra/node.d.ts → base/sources/node/index.d.cts} +35 -37
  71. package/dist/{extra/node.d.cts → base/sources/node/index.d.ts} +35 -37
  72. package/dist/base/sources/node/index.js +306 -0
  73. package/dist/base/sources/node/index.js.map +1 -0
  74. package/dist/base/utils/index.cjs +37 -0
  75. package/dist/base/utils/index.cjs.map +1 -0
  76. package/dist/base/utils/index.d.cts +37 -0
  77. package/dist/base/utils/index.d.ts +37 -0
  78. package/dist/base/utils/index.js +11 -0
  79. package/dist/base/utils/index.js.map +1 -0
  80. package/dist/base/worker/index.cjs +548 -0
  81. package/dist/base/worker/index.cjs.map +1 -0
  82. package/dist/base/worker/index.d.cts +207 -0
  83. package/dist/base/worker/index.d.ts +207 -0
  84. package/dist/base/worker/index.js +20 -0
  85. package/dist/base/worker/index.js.map +1 -0
  86. package/dist/breaker-C9skL3d8.d.ts +175 -0
  87. package/dist/breaker-ugSdq54q.d.cts +175 -0
  88. package/dist/{cascading-BglDkMdX.d.cts → cascading-CSSbKGrJ.d.ts} +3 -3
  89. package/dist/{cascading-MFgxu7Yo.d.ts → cascading-baGkiihI.d.cts} +3 -3
  90. package/dist/chunk-255UCBG4.js +58 -0
  91. package/dist/chunk-255UCBG4.js.map +1 -0
  92. package/dist/chunk-2LO3EL4W.js +1 -0
  93. package/dist/chunk-2LO3EL4W.js.map +1 -0
  94. package/dist/chunk-2OB3CEJS.js +1065 -0
  95. package/dist/chunk-2OB3CEJS.js.map +1 -0
  96. package/dist/chunk-36NMM65U.js +144 -0
  97. package/dist/chunk-36NMM65U.js.map +1 -0
  98. package/dist/chunk-3CEXCBN6.js +1 -0
  99. package/dist/chunk-3CEXCBN6.js.map +1 -0
  100. package/dist/chunk-3MUSLI6E.js +105 -0
  101. package/dist/chunk-3MUSLI6E.js.map +1 -0
  102. package/dist/chunk-3PSLNJDU.js +884 -0
  103. package/dist/chunk-3PSLNJDU.js.map +1 -0
  104. package/dist/chunk-3QZY5BI7.js +92 -0
  105. package/dist/chunk-3QZY5BI7.js.map +1 -0
  106. package/dist/chunk-42FQ27MQ.js +594 -0
  107. package/dist/chunk-42FQ27MQ.js.map +1 -0
  108. package/dist/chunk-4GYMCUDZ.js +1085 -0
  109. package/dist/chunk-4GYMCUDZ.js.map +1 -0
  110. package/dist/chunk-4S53H2KR.js +382 -0
  111. package/dist/chunk-4S53H2KR.js.map +1 -0
  112. package/dist/chunk-4XCHZRUJ.js +128 -0
  113. package/dist/chunk-4XCHZRUJ.js.map +1 -0
  114. package/dist/chunk-5THCXDWY.js +725 -0
  115. package/dist/chunk-5THCXDWY.js.map +1 -0
  116. package/dist/chunk-6XZYT4SW.js +256 -0
  117. package/dist/chunk-6XZYT4SW.js.map +1 -0
  118. package/dist/chunk-7EGRP2VX.js +76 -0
  119. package/dist/chunk-7EGRP2VX.js.map +1 -0
  120. package/dist/chunk-A7KV5UK4.js +150 -0
  121. package/dist/chunk-A7KV5UK4.js.map +1 -0
  122. package/dist/chunk-APY2SS5X.js +156 -0
  123. package/dist/chunk-APY2SS5X.js.map +1 -0
  124. package/dist/chunk-AZDQPQ3V.js +66 -0
  125. package/dist/chunk-AZDQPQ3V.js.map +1 -0
  126. package/dist/chunk-BU3SEFA5.js +90 -0
  127. package/dist/chunk-BU3SEFA5.js.map +1 -0
  128. package/dist/chunk-BXGZFGZ4.js +189 -0
  129. package/dist/chunk-BXGZFGZ4.js.map +1 -0
  130. package/dist/chunk-CGHORL6G.js +579 -0
  131. package/dist/chunk-CGHORL6G.js.map +1 -0
  132. package/dist/chunk-CXANAIZU.js +530 -0
  133. package/dist/chunk-CXANAIZU.js.map +1 -0
  134. package/dist/chunk-CZQHCKKG.js +1 -0
  135. package/dist/chunk-CZQHCKKG.js.map +1 -0
  136. package/dist/chunk-DKNHAICT.js +133 -0
  137. package/dist/chunk-DKNHAICT.js.map +1 -0
  138. package/dist/chunk-DM4OMPWK.js +584 -0
  139. package/dist/chunk-DM4OMPWK.js.map +1 -0
  140. package/dist/chunk-DMSNO6ZB.js +452 -0
  141. package/dist/chunk-DMSNO6ZB.js.map +1 -0
  142. package/dist/chunk-E5OZPDIW.js +229 -0
  143. package/dist/chunk-E5OZPDIW.js.map +1 -0
  144. package/dist/chunk-EVYY4X5A.js +509 -0
  145. package/dist/chunk-EVYY4X5A.js.map +1 -0
  146. package/dist/chunk-FDFD67UO.js +1 -0
  147. package/dist/chunk-FDFD67UO.js.map +1 -0
  148. package/dist/chunk-FMPF42Q4.js +13 -0
  149. package/dist/chunk-FMPF42Q4.js.map +1 -0
  150. package/dist/chunk-FR6RGA3B.js +1277 -0
  151. package/dist/chunk-FR6RGA3B.js.map +1 -0
  152. package/dist/chunk-FW23JYNQ.js +454 -0
  153. package/dist/chunk-FW23JYNQ.js.map +1 -0
  154. package/dist/chunk-GBCENOLN.js +1575 -0
  155. package/dist/chunk-GBCENOLN.js.map +1 -0
  156. package/dist/chunk-HL7HUJIX.js +1 -0
  157. package/dist/chunk-HL7HUJIX.js.map +1 -0
  158. package/dist/chunk-HULCUY35.js +2508 -0
  159. package/dist/chunk-HULCUY35.js.map +1 -0
  160. package/dist/chunk-IHTWQEDR.js +169 -0
  161. package/dist/chunk-IHTWQEDR.js.map +1 -0
  162. package/dist/chunk-IJRR6YAI.js +128 -0
  163. package/dist/chunk-IJRR6YAI.js.map +1 -0
  164. package/dist/chunk-JGFRAFDL.js +221 -0
  165. package/dist/chunk-JGFRAFDL.js.map +1 -0
  166. package/dist/chunk-KIIXR252.js +211 -0
  167. package/dist/chunk-KIIXR252.js.map +1 -0
  168. package/dist/chunk-KN3H5CNT.js +11 -0
  169. package/dist/chunk-KN3H5CNT.js.map +1 -0
  170. package/dist/chunk-KPG3DGLA.js +1 -0
  171. package/dist/chunk-KPG3DGLA.js.map +1 -0
  172. package/dist/chunk-KRNQ6RGQ.js +1 -0
  173. package/dist/chunk-KRNQ6RGQ.js.map +1 -0
  174. package/dist/chunk-LBAJK24K.js +1071 -0
  175. package/dist/chunk-LBAJK24K.js.map +1 -0
  176. package/dist/chunk-MLTPJMH6.js +417 -0
  177. package/dist/chunk-MLTPJMH6.js.map +1 -0
  178. package/dist/chunk-N3SZ7BMH.js +95 -0
  179. package/dist/chunk-N3SZ7BMH.js.map +1 -0
  180. package/dist/chunk-NDUD3IMO.js +540 -0
  181. package/dist/chunk-NDUD3IMO.js.map +1 -0
  182. package/dist/chunk-NY2PYHNC.js +873 -0
  183. package/dist/chunk-NY2PYHNC.js.map +1 -0
  184. package/dist/chunk-O3MT7DYI.js +225 -0
  185. package/dist/chunk-O3MT7DYI.js.map +1 -0
  186. package/dist/chunk-OCUDSN63.js +2386 -0
  187. package/dist/chunk-OCUDSN63.js.map +1 -0
  188. package/dist/chunk-OIWU3NYV.js +199 -0
  189. package/dist/chunk-OIWU3NYV.js.map +1 -0
  190. package/dist/chunk-OO5BM6CJ.js +1153 -0
  191. package/dist/chunk-OO5BM6CJ.js.map +1 -0
  192. package/dist/chunk-OQUIJT7A.js +1 -0
  193. package/dist/chunk-OQUIJT7A.js.map +1 -0
  194. package/dist/chunk-P5LBT622.js +105 -0
  195. package/dist/chunk-P5LBT622.js.map +1 -0
  196. package/dist/chunk-PKGQG5QQ.js +519 -0
  197. package/dist/chunk-PKGQG5QQ.js.map +1 -0
  198. package/dist/chunk-PKPO3JTZ.js +561 -0
  199. package/dist/chunk-PKPO3JTZ.js.map +1 -0
  200. package/dist/chunk-PL5UDIQ5.js +118 -0
  201. package/dist/chunk-PL5UDIQ5.js.map +1 -0
  202. package/dist/chunk-PZWISPIQ.js +432 -0
  203. package/dist/chunk-PZWISPIQ.js.map +1 -0
  204. package/dist/chunk-Q3EYOCZB.js +510 -0
  205. package/dist/chunk-Q3EYOCZB.js.map +1 -0
  206. package/dist/chunk-QMBYUVRL.js +15 -0
  207. package/dist/chunk-QMBYUVRL.js.map +1 -0
  208. package/dist/chunk-RAGGHLCV.js +200 -0
  209. package/dist/chunk-RAGGHLCV.js.map +1 -0
  210. package/dist/chunk-RGL53X5G.js +574 -0
  211. package/dist/chunk-RGL53X5G.js.map +1 -0
  212. package/dist/chunk-RJOG4IJU.js +1039 -0
  213. package/dist/chunk-RJOG4IJU.js.map +1 -0
  214. package/dist/chunk-SOOKUYVM.js +403 -0
  215. package/dist/chunk-SOOKUYVM.js.map +1 -0
  216. package/dist/chunk-T5BN5KG7.js +1 -0
  217. package/dist/chunk-T5BN5KG7.js.map +1 -0
  218. package/dist/chunk-TP7244Y6.js +207 -0
  219. package/dist/chunk-TP7244Y6.js.map +1 -0
  220. package/dist/chunk-TSBFTJKM.js +57 -0
  221. package/dist/chunk-TSBFTJKM.js.map +1 -0
  222. package/dist/chunk-URQ2CBBF.js +143 -0
  223. package/dist/chunk-URQ2CBBF.js.map +1 -0
  224. package/dist/chunk-W2BOPXTI.js +1 -0
  225. package/dist/chunk-W2BOPXTI.js.map +1 -0
  226. package/dist/chunk-WKSWLSCX.js +207 -0
  227. package/dist/chunk-WKSWLSCX.js.map +1 -0
  228. package/dist/chunk-Y52CS6YA.js +88 -0
  229. package/dist/chunk-Y52CS6YA.js.map +1 -0
  230. package/dist/chunk-YCBUWK77.js +92 -0
  231. package/dist/chunk-YCBUWK77.js.map +1 -0
  232. package/dist/chunk-YJ4U2D2C.js +314 -0
  233. package/dist/chunk-YJ4U2D2C.js.map +1 -0
  234. package/dist/chunk-Z4YXAUDN.js +239 -0
  235. package/dist/chunk-Z4YXAUDN.js.map +1 -0
  236. package/dist/chunk-Z6EGP5D7.js +92 -0
  237. package/dist/chunk-Z6EGP5D7.js.map +1 -0
  238. package/dist/compat/index.cjs +3100 -9
  239. package/dist/compat/index.cjs.map +1 -0
  240. package/dist/compat/index.d.cts +112 -18
  241. package/dist/compat/index.d.ts +112 -18
  242. package/dist/compat/index.js +176 -1
  243. package/dist/compat/index.js.map +1 -0
  244. package/dist/compat/jotai/index.cjs +149 -1
  245. package/dist/compat/jotai/index.cjs.map +1 -0
  246. package/dist/compat/jotai/index.d.cts +2 -2
  247. package/dist/compat/jotai/index.d.ts +2 -2
  248. package/dist/compat/jotai/index.js +8 -1
  249. package/dist/compat/jotai/index.js.map +1 -0
  250. package/dist/compat/nanostores/index.cjs +205 -1
  251. package/dist/compat/nanostores/index.cjs.map +1 -0
  252. package/dist/compat/nanostores/index.d.cts +2 -2
  253. package/dist/compat/nanostores/index.d.ts +2 -2
  254. package/dist/compat/nanostores/index.js +22 -1
  255. package/dist/compat/nanostores/index.js.map +1 -0
  256. package/dist/compat/nestjs/index.cjs +2241 -9
  257. package/dist/compat/nestjs/index.cjs.map +1 -0
  258. package/dist/compat/nestjs/index.d.cts +7 -10
  259. package/dist/compat/nestjs/index.d.ts +7 -10
  260. package/dist/compat/nestjs/index.js +78 -1
  261. package/dist/compat/nestjs/index.js.map +1 -0
  262. package/dist/compat/react/index.cjs +114 -1
  263. package/dist/compat/react/index.cjs.map +1 -0
  264. package/dist/compat/react/index.d.cts +2 -2
  265. package/dist/compat/react/index.d.ts +2 -2
  266. package/dist/compat/react/index.js +12 -1
  267. package/dist/compat/react/index.js.map +1 -0
  268. package/dist/compat/solid/index.cjs +101 -1
  269. package/dist/compat/solid/index.cjs.map +1 -0
  270. package/dist/compat/solid/index.d.cts +2 -2
  271. package/dist/compat/solid/index.d.ts +2 -2
  272. package/dist/compat/solid/index.js +12 -1
  273. package/dist/compat/solid/index.js.map +1 -0
  274. package/dist/compat/svelte/index.cjs +104 -1
  275. package/dist/compat/svelte/index.cjs.map +1 -0
  276. package/dist/compat/svelte/index.d.cts +2 -2
  277. package/dist/compat/svelte/index.d.ts +2 -2
  278. package/dist/compat/svelte/index.js +12 -1
  279. package/dist/compat/svelte/index.js.map +1 -0
  280. package/dist/compat/vue/index.cjs +119 -1
  281. package/dist/compat/vue/index.cjs.map +1 -0
  282. package/dist/compat/vue/index.d.cts +2 -2
  283. package/dist/compat/vue/index.d.ts +2 -2
  284. package/dist/compat/vue/index.js +12 -1
  285. package/dist/compat/vue/index.js.map +1 -0
  286. package/dist/compat/zustand/index.cjs +69 -3
  287. package/dist/compat/zustand/index.cjs.map +1 -0
  288. package/dist/compat/zustand/index.d.cts +2 -6
  289. package/dist/compat/zustand/index.d.ts +2 -6
  290. package/dist/compat/zustand/index.js +8 -1
  291. package/dist/compat/zustand/index.js.map +1 -0
  292. package/dist/distill-De6Rnn15.d.cts +48 -0
  293. package/dist/distill-De6Rnn15.d.ts +48 -0
  294. package/dist/external-register-CWyroXb_.d.cts +138 -0
  295. package/dist/external-register-CWyroXb_.d.ts +138 -0
  296. package/dist/{fallback-74oxi34l.d.cts → fallback-Bx46zqky.d.cts} +3 -10
  297. package/dist/{fallback-DUyyBTBK.d.ts → fallback-pIWW8A2d.d.ts} +3 -10
  298. package/dist/guarded-execution-BcdtxeBk.d.ts +207 -0
  299. package/dist/guarded-execution-C-3hnP6A.d.cts +207 -0
  300. package/dist/{index-CBGUK09R.d.ts → index-5SU_O78r.d.cts} +5 -5
  301. package/dist/{index-BmZXHqkE.d.ts → index-B6pxYJzO.d.cts} +1 -1
  302. package/dist/{index-hcDJ8PSI.d.cts → index-B6pxYJzO.d.ts} +1 -1
  303. package/dist/{index-C5stwKcw.d.cts → index-BFsng6v1.d.cts} +1 -1
  304. package/dist/{index-CdAlHFEt.d.ts → index-BFsng6v1.d.ts} +1 -1
  305. package/dist/{index-_6ODbuOu.d.cts → index-Bg-LwEt-.d.cts} +1 -1
  306. package/dist/{index-CviRnE4K.d.ts → index-Bg-LwEt-.d.ts} +1 -1
  307. package/dist/{index-CBBLl_rc.d.ts → index-Brp888t0.d.cts} +1 -1
  308. package/dist/{index-BQSKmbuG.d.cts → index-Brp888t0.d.ts} +1 -1
  309. package/dist/{index-sqkqlb1p.d.ts → index-CDfk6jHN.d.cts} +1 -1
  310. package/dist/{index-ZVQhLa2i.d.cts → index-CDfk6jHN.d.ts} +1 -1
  311. package/dist/{index-Climxqsu.d.cts → index-CEXCtYYJ.d.ts} +5 -5
  312. package/dist/index-DLAxYaN5.d.cts +169 -0
  313. package/dist/index-DLAxYaN5.d.ts +169 -0
  314. package/dist/{index-CK29LV56.d.cts → index-DeWbQzMe.d.cts} +1 -1
  315. package/dist/{index-CPQlGA29.d.ts → index-DeWbQzMe.d.ts} +1 -1
  316. package/dist/{index-BrPrLl4e.d.cts → index-dX9IzPqj.d.cts} +1 -1
  317. package/dist/{index-Dgl1HpPn.d.ts → index-dX9IzPqj.d.ts} +1 -1
  318. package/dist/index.cjs +25934 -191
  319. package/dist/index.cjs.map +1 -0
  320. package/dist/index.d.cts +58 -94
  321. package/dist/index.d.ts +58 -94
  322. package/dist/index.js +852 -1
  323. package/dist/index.js.map +1 -0
  324. package/dist/layout-types-B5aiHYgk.d.cts +72 -0
  325. package/dist/layout-types-B5aiHYgk.d.ts +72 -0
  326. package/dist/memory-composers-BryDrRBX.d.cts +529 -0
  327. package/dist/memory-composers-CVQqPYEV.d.ts +529 -0
  328. package/dist/{observable-DWjNfLvC.d.ts → observable-BXQoW1P-.d.cts} +1 -1
  329. package/dist/{observable-e3eiPPFy.d.cts → observable-BXQoW1P-.d.ts} +1 -1
  330. package/dist/{pipeline-graph-Sgj0gCwn.d.ts → pipeline-graph-Ce47CB6Y.d.cts} +13 -10
  331. package/dist/{pipeline-graph-CIKhynsF.d.cts → pipeline-graph-DXCwY9vG.d.ts} +13 -10
  332. package/dist/presets/ai/index.cjs +4377 -0
  333. package/dist/presets/ai/index.cjs.map +1 -0
  334. package/dist/presets/ai/index.d.cts +98 -0
  335. package/dist/presets/ai/index.d.ts +98 -0
  336. package/dist/presets/ai/index.js +54 -0
  337. package/dist/presets/ai/index.js.map +1 -0
  338. package/dist/presets/harness/index.cjs +5929 -0
  339. package/dist/presets/harness/index.cjs.map +1 -0
  340. package/dist/presets/harness/index.d.cts +566 -0
  341. package/dist/presets/harness/index.d.ts +566 -0
  342. package/dist/presets/harness/index.js +71 -0
  343. package/dist/presets/harness/index.js.map +1 -0
  344. package/dist/presets/index.cjs +9782 -0
  345. package/dist/presets/index.cjs.map +1 -0
  346. package/dist/presets/index.d.cts +28 -0
  347. package/dist/presets/index.d.ts +28 -0
  348. package/dist/presets/index.js +129 -0
  349. package/dist/presets/index.js.map +1 -0
  350. package/dist/presets/inspect/index.cjs +1087 -0
  351. package/dist/presets/inspect/index.cjs.map +1 -0
  352. package/dist/presets/inspect/index.d.cts +172 -0
  353. package/dist/presets/inspect/index.d.ts +172 -0
  354. package/dist/presets/inspect/index.js +21 -0
  355. package/dist/presets/inspect/index.js.map +1 -0
  356. package/dist/presets/resilience/index.cjs +1593 -0
  357. package/dist/presets/resilience/index.cjs.map +1 -0
  358. package/dist/presets/resilience/index.d.cts +205 -0
  359. package/dist/presets/resilience/index.d.ts +205 -0
  360. package/dist/presets/resilience/index.js +18 -0
  361. package/dist/presets/resilience/index.js.map +1 -0
  362. package/dist/rate-limiter-CEALq4N1.d.ts +559 -0
  363. package/dist/rate-limiter-DpVbSYdH.d.cts +559 -0
  364. package/dist/{reactive-layout-DOTs9P3X.d.ts → reactive-layout-fswlBUvX.d.cts} +19 -7
  365. package/dist/{reactive-layout-DgctbqZo.d.cts → reactive-layout-fswlBUvX.d.ts} +19 -7
  366. package/dist/retry-BDbRZ_gx.d.ts +125 -0
  367. package/dist/retry-DWuhjvsA.d.cts +125 -0
  368. package/dist/solutions/index.cjs +8200 -0
  369. package/dist/solutions/index.cjs.map +1 -0
  370. package/dist/solutions/index.d.cts +23 -0
  371. package/dist/solutions/index.d.ts +23 -0
  372. package/dist/solutions/index.js +55 -0
  373. package/dist/solutions/index.js.map +1 -0
  374. package/dist/spawnable-5mDY501F.d.cts +746 -0
  375. package/dist/spawnable-D3lR0oQu.d.ts +746 -0
  376. package/dist/status-U-rUI79b.d.cts +84 -0
  377. package/dist/status-U-rUI79b.d.ts +84 -0
  378. package/dist/timeout-U5O4ESK3.js +12 -0
  379. package/dist/timeout-U5O4ESK3.js.map +1 -0
  380. package/dist/{types-CWFysE9E.d.ts → types-BB5Lw-pB.d.cts} +3 -3
  381. package/dist/{types-C0_yquda.d.cts → types-BB5Lw-pB.d.ts} +3 -3
  382. package/dist/types-CJWIMJiZ.d.ts +548 -0
  383. package/dist/types-vCq7ShIm.d.cts +548 -0
  384. package/dist/utils/ai/browser.cjs +2169 -0
  385. package/dist/utils/ai/browser.cjs.map +1 -0
  386. package/dist/{patterns → utils}/ai/browser.d.cts +7 -5
  387. package/dist/{patterns → utils}/ai/browser.d.ts +7 -5
  388. package/dist/utils/ai/browser.js +255 -0
  389. package/dist/utils/ai/browser.js.map +1 -0
  390. package/dist/utils/ai/index.cjs +8468 -0
  391. package/dist/utils/ai/index.cjs.map +1 -0
  392. package/dist/{index-CR8QpwX8.d.ts → utils/ai/index.d.cts} +73 -976
  393. package/dist/{index-UPSiS-X7.d.cts → utils/ai/index.d.ts} +73 -976
  394. package/dist/utils/ai/index.js +173 -0
  395. package/dist/utils/ai/index.js.map +1 -0
  396. package/dist/utils/ai/node.cjs +648 -0
  397. package/dist/utils/ai/node.cjs.map +1 -0
  398. package/dist/{patterns → utils}/ai/node.d.cts +5 -7
  399. package/dist/{patterns → utils}/ai/node.d.ts +5 -7
  400. package/dist/utils/ai/node.js +84 -0
  401. package/dist/utils/ai/node.js.map +1 -0
  402. package/dist/utils/cqrs/index.cjs +1036 -0
  403. package/dist/utils/cqrs/index.cjs.map +1 -0
  404. package/dist/{index-CeFiHtAg.d.ts → utils/cqrs/index.d.cts} +7 -37
  405. package/dist/{index-B-_tFaqV.d.cts → utils/cqrs/index.d.ts} +7 -37
  406. package/dist/utils/cqrs/index.js +18 -0
  407. package/dist/utils/cqrs/index.js.map +1 -0
  408. package/dist/utils/demo-shell/index.cjs +865 -0
  409. package/dist/utils/demo-shell/index.cjs.map +1 -0
  410. package/dist/{index-B8YnZpIR.d.ts → utils/demo-shell/index.d.cts} +4 -16
  411. package/dist/{index-Cwv0KWcU.d.cts → utils/demo-shell/index.d.ts} +4 -16
  412. package/dist/utils/demo-shell/index.js +13 -0
  413. package/dist/utils/demo-shell/index.js.map +1 -0
  414. package/dist/utils/domain-templates/index.cjs +732 -0
  415. package/dist/utils/domain-templates/index.cjs.map +1 -0
  416. package/dist/{index-CzLVrjxn.d.ts → utils/domain-templates/index.d.cts} +3 -20
  417. package/dist/{index-BaQaY_IQ.d.cts → utils/domain-templates/index.d.ts} +3 -20
  418. package/dist/utils/domain-templates/index.js +17 -0
  419. package/dist/utils/domain-templates/index.js.map +1 -0
  420. package/dist/utils/graphspec/index.cjs +1174 -0
  421. package/dist/utils/graphspec/index.cjs.map +1 -0
  422. package/dist/{index-CMh5Rz1y.d.ts → utils/graphspec/index.d.cts} +106 -42
  423. package/dist/{index-CS0LTlB8.d.cts → utils/graphspec/index.d.ts} +106 -42
  424. package/dist/utils/graphspec/index.js +35 -0
  425. package/dist/utils/graphspec/index.js.map +1 -0
  426. package/dist/utils/harness/index.cjs +656 -0
  427. package/dist/utils/harness/index.cjs.map +1 -0
  428. package/dist/utils/harness/index.d.cts +542 -0
  429. package/dist/utils/harness/index.d.ts +542 -0
  430. package/dist/utils/harness/index.js +56 -0
  431. package/dist/utils/harness/index.js.map +1 -0
  432. package/dist/utils/index.cjs +17609 -0
  433. package/dist/utils/index.cjs.map +1 -0
  434. package/dist/utils/index.d.cts +96 -0
  435. package/dist/utils/index.d.ts +96 -0
  436. package/dist/utils/index.js +514 -0
  437. package/dist/utils/index.js.map +1 -0
  438. package/dist/utils/inspect/index.cjs +807 -0
  439. package/dist/utils/inspect/index.cjs.map +1 -0
  440. package/dist/utils/inspect/index.d.cts +123 -0
  441. package/dist/utils/inspect/index.d.ts +123 -0
  442. package/dist/utils/inspect/index.js +30 -0
  443. package/dist/utils/inspect/index.js.map +1 -0
  444. package/dist/utils/job-queue/index.cjs +717 -0
  445. package/dist/utils/job-queue/index.cjs.map +1 -0
  446. package/dist/{index-DisjX8a-.d.ts → utils/job-queue/index.d.cts} +5 -26
  447. package/dist/{index-DV_1YuVk.d.cts → utils/job-queue/index.d.ts} +5 -26
  448. package/dist/utils/job-queue/index.js +18 -0
  449. package/dist/utils/job-queue/index.js.map +1 -0
  450. package/dist/utils/memory/index.cjs +1451 -0
  451. package/dist/utils/memory/index.cjs.map +1 -0
  452. package/dist/{index-CZ3r5Rxp.d.ts → utils/memory/index.d.cts} +242 -34
  453. package/dist/{index-B17QddL1.d.cts → utils/memory/index.d.ts} +242 -34
  454. package/dist/utils/memory/index.js +19 -0
  455. package/dist/utils/memory/index.js.map +1 -0
  456. package/dist/utils/messaging/index.cjs +666 -0
  457. package/dist/utils/messaging/index.cjs.map +1 -0
  458. package/dist/utils/messaging/index.d.cts +562 -0
  459. package/dist/utils/messaging/index.d.ts +562 -0
  460. package/dist/utils/messaging/index.js +50 -0
  461. package/dist/utils/messaging/index.js.map +1 -0
  462. package/dist/utils/orchestration/index.cjs +876 -0
  463. package/dist/utils/orchestration/index.cjs.map +1 -0
  464. package/dist/utils/orchestration/index.d.cts +233 -0
  465. package/dist/utils/orchestration/index.d.ts +233 -0
  466. package/dist/utils/orchestration/index.js +19 -0
  467. package/dist/utils/orchestration/index.js.map +1 -0
  468. package/dist/utils/process/index.cjs +743 -0
  469. package/dist/utils/process/index.cjs.map +1 -0
  470. package/dist/{index-p09KSrTN.d.ts → utils/process/index.d.cts} +97 -44
  471. package/dist/{index-CasX6Pfq.d.cts → utils/process/index.d.ts} +97 -44
  472. package/dist/utils/process/index.js +14 -0
  473. package/dist/utils/process/index.js.map +1 -0
  474. package/dist/utils/reactive-layout/index.cjs +1607 -0
  475. package/dist/utils/reactive-layout/index.cjs.map +1 -0
  476. package/dist/{index-B5S8ULbU.d.ts → utils/reactive-layout/index.d.cts} +58 -81
  477. package/dist/{index-Dc4AYqrJ.d.cts → utils/reactive-layout/index.d.ts} +58 -81
  478. package/dist/utils/reactive-layout/index.js +52 -0
  479. package/dist/utils/reactive-layout/index.js.map +1 -0
  480. package/dist/utils/reduction/index.cjs +203 -0
  481. package/dist/utils/reduction/index.cjs.map +1 -0
  482. package/dist/{index-Byu-OpX_.d.ts → utils/reduction/index.d.cts} +6 -17
  483. package/dist/{index-tRCxuAXF.d.cts → utils/reduction/index.d.ts} +6 -17
  484. package/dist/utils/reduction/index.js +14 -0
  485. package/dist/utils/reduction/index.js.map +1 -0
  486. package/dist/utils/resilience/index.cjs +1617 -0
  487. package/dist/utils/resilience/index.cjs.map +1 -0
  488. package/dist/utils/resilience/index.d.cts +9 -0
  489. package/dist/utils/resilience/index.d.ts +9 -0
  490. package/dist/utils/resilience/index.js +44 -0
  491. package/dist/utils/resilience/index.js.map +1 -0
  492. package/dist/utils/surface/index.cjs +1070 -0
  493. package/dist/utils/surface/index.cjs.map +1 -0
  494. package/dist/{index-CYq8vAyV.d.ts → utils/surface/index.d.cts} +7 -58
  495. package/dist/{index-CSOmP7xT.d.cts → utils/surface/index.d.ts} +7 -58
  496. package/dist/utils/surface/index.js +30 -0
  497. package/dist/utils/surface/index.js.map +1 -0
  498. package/dist/utils/topology-view/index.cjs +620 -0
  499. package/dist/utils/topology-view/index.cjs.map +1 -0
  500. package/dist/utils/topology-view/index.d.cts +68 -0
  501. package/dist/utils/topology-view/index.d.ts +68 -0
  502. package/dist/utils/topology-view/index.js +11 -0
  503. package/dist/utils/topology-view/index.js.map +1 -0
  504. package/package.json +664 -584
  505. package/dist/backoff-HPZMEZNF.js +0 -1
  506. package/dist/chunk-2T7U5EU6.js +0 -1
  507. package/dist/chunk-3G5U5QNE.js +0 -5
  508. package/dist/chunk-4VVTGLXJ.js +0 -1
  509. package/dist/chunk-5M4CCMMD.js +0 -45
  510. package/dist/chunk-5QDBSZBV.js +0 -1
  511. package/dist/chunk-5XJ6B66J.js +0 -1
  512. package/dist/chunk-6QZNQS5B.js +0 -1
  513. package/dist/chunk-6X7AFUJV.js +0 -9
  514. package/dist/chunk-7K6PWTDQ.js +0 -1
  515. package/dist/chunk-7LIAPXJB.js +0 -1
  516. package/dist/chunk-7WPU3UHQ.js +0 -1
  517. package/dist/chunk-A5WCQ5NO.js +0 -1
  518. package/dist/chunk-APPIWSGD.js +0 -84
  519. package/dist/chunk-BEZWM2SY.js +0 -1
  520. package/dist/chunk-C72GO4IZ.js +0 -1
  521. package/dist/chunk-CB676TKJ.js +0 -1
  522. package/dist/chunk-CE6TI2TL.js +0 -1
  523. package/dist/chunk-CE72X3WO.js +0 -1
  524. package/dist/chunk-CK2E7BTU.js +0 -1
  525. package/dist/chunk-CLVB32RD.js +0 -1
  526. package/dist/chunk-CRVT7D2P.js +0 -1
  527. package/dist/chunk-D5RFJOZ2.js +0 -1
  528. package/dist/chunk-D7GPHKFH.js +0 -1
  529. package/dist/chunk-DHRX7JX4.js +0 -2
  530. package/dist/chunk-ESMPEKEV.js +0 -1
  531. package/dist/chunk-F672GV32.js +0 -1
  532. package/dist/chunk-FZMYDOWV.js +0 -1
  533. package/dist/chunk-GHBWHMRZ.js +0 -1
  534. package/dist/chunk-GLERH466.js +0 -1
  535. package/dist/chunk-GPW2V3RE.js +0 -1
  536. package/dist/chunk-HIDYF36O.js +0 -1
  537. package/dist/chunk-HITNVN6B.js +0 -3
  538. package/dist/chunk-HY4DJBA7.js +0 -5
  539. package/dist/chunk-KZIEYVXN.js +0 -1
  540. package/dist/chunk-L6NSJVJZ.js +0 -1
  541. package/dist/chunk-N4MQX6JU.js +0 -18
  542. package/dist/chunk-N7FHEL4D.js +0 -1
  543. package/dist/chunk-NTEURFZH.js +0 -1
  544. package/dist/chunk-OIVP6KFV.js +0 -1
  545. package/dist/chunk-OPHBU3LG.js +0 -1
  546. package/dist/chunk-OYQOZP2F.js +0 -5
  547. package/dist/chunk-PTZK576G.js +0 -1
  548. package/dist/chunk-QYADASLV.js +0 -1
  549. package/dist/chunk-ST7UXLWR.js +0 -1
  550. package/dist/chunk-SVY7VUYU.js +0 -1
  551. package/dist/chunk-TK3NWWD4.js +0 -1
  552. package/dist/chunk-TSOYJ743.js +0 -1
  553. package/dist/chunk-UNGSTR4X.js +0 -61
  554. package/dist/chunk-VIMF6LGM.js +0 -1
  555. package/dist/chunk-VJLMUKOI.js +0 -1
  556. package/dist/chunk-VN6RDSK2.js +0 -1
  557. package/dist/chunk-VV4N5P64.js +0 -1
  558. package/dist/chunk-W3I423PS.js +0 -1
  559. package/dist/chunk-WJR24TAG.js +0 -1
  560. package/dist/chunk-XTGKMHSW.js +0 -1
  561. package/dist/chunk-YBB7ZGTY.js +0 -1
  562. package/dist/chunk-Z4NPUARF.js +0 -1
  563. package/dist/chunk-ZGNQRPDT.js +0 -1
  564. package/dist/chunk-ZKPSFFKU.js +0 -1
  565. package/dist/chunk-ZLV5SQSX.js +0 -1
  566. package/dist/content-addressed-storage-4-ST1tYk.d.cts +0 -124
  567. package/dist/content-addressed-storage-DuYMjV7o.d.ts +0 -124
  568. package/dist/core/index.cjs +0 -1
  569. package/dist/core/index.d.cts +0 -3
  570. package/dist/core/index.d.ts +0 -3
  571. package/dist/core/index.js +0 -1
  572. package/dist/decay-BvOWTZ00.d.ts +0 -112
  573. package/dist/decay-CFlLvXUT.d.cts +0 -112
  574. package/dist/extra/browser.cjs +0 -1
  575. package/dist/extra/browser.d.cts +0 -4
  576. package/dist/extra/browser.d.ts +0 -4
  577. package/dist/extra/browser.js +0 -1
  578. package/dist/extra/index.cjs +0 -20
  579. package/dist/extra/index.d.cts +0 -17
  580. package/dist/extra/index.d.ts +0 -17
  581. package/dist/extra/index.js +0 -1
  582. package/dist/extra/node.cjs +0 -2
  583. package/dist/extra/node.js +0 -2
  584. package/dist/extra/operators.cjs +0 -1
  585. package/dist/extra/operators.d.cts +0 -958
  586. package/dist/extra/operators.d.ts +0 -958
  587. package/dist/extra/operators.js +0 -1
  588. package/dist/extra/reactive.cjs +0 -1
  589. package/dist/extra/reactive.d.cts +0 -353
  590. package/dist/extra/reactive.d.ts +0 -353
  591. package/dist/extra/reactive.js +0 -1
  592. package/dist/extra/render/index.cjs +0 -5
  593. package/dist/extra/render/index.js +0 -1
  594. package/dist/extra/sources.cjs +0 -3
  595. package/dist/extra/sources.js +0 -1
  596. package/dist/extra/storage-browser.cjs +0 -1
  597. package/dist/extra/storage-browser.d.cts +0 -37
  598. package/dist/extra/storage-browser.d.ts +0 -37
  599. package/dist/extra/storage-browser.js +0 -1
  600. package/dist/extra/storage-core.cjs +0 -1
  601. package/dist/extra/storage-core.d.cts +0 -28
  602. package/dist/extra/storage-core.d.ts +0 -28
  603. package/dist/extra/storage-core.js +0 -1
  604. package/dist/extra/storage-node.cjs +0 -1
  605. package/dist/extra/storage-node.d.cts +0 -2
  606. package/dist/extra/storage-node.d.ts +0 -2
  607. package/dist/extra/storage-node.js +0 -0
  608. package/dist/extra/storage-tiers-browser.cjs +0 -1
  609. package/dist/extra/storage-tiers-browser.d.cts +0 -120
  610. package/dist/extra/storage-tiers-browser.d.ts +0 -120
  611. package/dist/extra/storage-tiers-browser.js +0 -1
  612. package/dist/extra/storage-tiers-node.cjs +0 -1
  613. package/dist/extra/storage-tiers-node.d.cts +0 -210
  614. package/dist/extra/storage-tiers-node.d.ts +0 -210
  615. package/dist/extra/storage-tiers-node.js +0 -1
  616. package/dist/extra/storage-tiers.cjs +0 -1
  617. package/dist/extra/storage-tiers.d.cts +0 -412
  618. package/dist/extra/storage-tiers.d.ts +0 -412
  619. package/dist/extra/storage-tiers.js +0 -1
  620. package/dist/graph/index.cjs +0 -7
  621. package/dist/graph/index.d.cts +0 -7
  622. package/dist/graph/index.d.ts +0 -7
  623. package/dist/graph/index.js +0 -1
  624. package/dist/graph-CWvEUQAq.d.cts +0 -1861
  625. package/dist/graph-D9LFnda9.d.ts +0 -1861
  626. package/dist/index-5k1T6jl0.d.cts +0 -121
  627. package/dist/index-9770hRuQ.d.cts +0 -779
  628. package/dist/index-B1F8Enjf.d.ts +0 -704
  629. package/dist/index-BHskSB8v.d.ts +0 -3413
  630. package/dist/index-BIYAkbAi.d.cts +0 -26
  631. package/dist/index-BoJ5JHxI.d.ts +0 -557
  632. package/dist/index-BocU7pqs.d.ts +0 -779
  633. package/dist/index-BxNs2HB9.d.cts +0 -1858
  634. package/dist/index-C1T3d7V-.d.cts +0 -704
  635. package/dist/index-C5ri2Axc.d.cts +0 -301
  636. package/dist/index-C9l6OEBL.d.ts +0 -26
  637. package/dist/index-CC-AvFTy.d.cts +0 -557
  638. package/dist/index-CJF1URuX.d.ts +0 -121
  639. package/dist/index-CdTelp1M.d.ts +0 -202
  640. package/dist/index-Cj3WohTd.d.cts +0 -202
  641. package/dist/index-Co7uli2l.d.cts +0 -3413
  642. package/dist/index-D0aciIex.d.cts +0 -209
  643. package/dist/index-DHen9Klo.d.ts +0 -1858
  644. package/dist/index-Yq60JP3s.d.ts +0 -209
  645. package/dist/index-nozs3fFC.d.ts +0 -301
  646. package/dist/node-kK3CvTrR.d.cts +0 -1347
  647. package/dist/node-kK3CvTrR.d.ts +0 -1347
  648. package/dist/patterns/ai/browser.cjs +0 -8
  649. package/dist/patterns/ai/browser.js +0 -3
  650. package/dist/patterns/ai/index.cjs +0 -74
  651. package/dist/patterns/ai/index.d.cts +0 -20
  652. package/dist/patterns/ai/index.d.ts +0 -20
  653. package/dist/patterns/ai/index.js +0 -1
  654. package/dist/patterns/ai/node.cjs +0 -1
  655. package/dist/patterns/ai/node.js +0 -1
  656. package/dist/patterns/cqrs/index.cjs +0 -3
  657. package/dist/patterns/cqrs/index.d.cts +0 -8
  658. package/dist/patterns/cqrs/index.d.ts +0 -8
  659. package/dist/patterns/cqrs/index.js +0 -1
  660. package/dist/patterns/demo-shell/index.cjs +0 -5
  661. package/dist/patterns/demo-shell/index.d.cts +0 -7
  662. package/dist/patterns/demo-shell/index.d.ts +0 -7
  663. package/dist/patterns/demo-shell/index.js +0 -1
  664. package/dist/patterns/domain-templates/index.cjs +0 -3
  665. package/dist/patterns/domain-templates/index.d.cts +0 -6
  666. package/dist/patterns/domain-templates/index.d.ts +0 -6
  667. package/dist/patterns/domain-templates/index.js +0 -1
  668. package/dist/patterns/graphspec/index.cjs +0 -86
  669. package/dist/patterns/graphspec/index.d.cts +0 -8
  670. package/dist/patterns/graphspec/index.d.ts +0 -8
  671. package/dist/patterns/graphspec/index.js +0 -1
  672. package/dist/patterns/harness/index.cjs +0 -48
  673. package/dist/patterns/harness/index.d.cts +0 -13
  674. package/dist/patterns/harness/index.d.ts +0 -13
  675. package/dist/patterns/harness/index.js +0 -1
  676. package/dist/patterns/inspect/index.cjs +0 -3
  677. package/dist/patterns/inspect/index.d.cts +0 -9
  678. package/dist/patterns/inspect/index.d.ts +0 -9
  679. package/dist/patterns/inspect/index.js +0 -1
  680. package/dist/patterns/job-queue/index.cjs +0 -3
  681. package/dist/patterns/job-queue/index.d.cts +0 -9
  682. package/dist/patterns/job-queue/index.d.ts +0 -9
  683. package/dist/patterns/job-queue/index.js +0 -1
  684. package/dist/patterns/memory/index.cjs +0 -3
  685. package/dist/patterns/memory/index.d.cts +0 -8
  686. package/dist/patterns/memory/index.d.ts +0 -8
  687. package/dist/patterns/memory/index.js +0 -1
  688. package/dist/patterns/messaging/index.cjs +0 -3
  689. package/dist/patterns/messaging/index.d.cts +0 -7
  690. package/dist/patterns/messaging/index.d.ts +0 -7
  691. package/dist/patterns/messaging/index.js +0 -1
  692. package/dist/patterns/orchestration/index.cjs +0 -3
  693. package/dist/patterns/orchestration/index.d.cts +0 -8
  694. package/dist/patterns/orchestration/index.d.ts +0 -8
  695. package/dist/patterns/orchestration/index.js +0 -1
  696. package/dist/patterns/process/index.cjs +0 -3
  697. package/dist/patterns/process/index.d.cts +0 -10
  698. package/dist/patterns/process/index.d.ts +0 -10
  699. package/dist/patterns/process/index.js +0 -1
  700. package/dist/patterns/reactive-layout/index.cjs +0 -4
  701. package/dist/patterns/reactive-layout/index.d.cts +0 -7
  702. package/dist/patterns/reactive-layout/index.d.ts +0 -7
  703. package/dist/patterns/reactive-layout/index.js +0 -1
  704. package/dist/patterns/reduction/index.cjs +0 -3
  705. package/dist/patterns/reduction/index.d.cts +0 -6
  706. package/dist/patterns/reduction/index.d.ts +0 -6
  707. package/dist/patterns/reduction/index.js +0 -1
  708. package/dist/patterns/surface/index.cjs +0 -13
  709. package/dist/patterns/surface/index.d.cts +0 -9
  710. package/dist/patterns/surface/index.d.ts +0 -9
  711. package/dist/patterns/surface/index.js +0 -1
  712. package/dist/reactive-log-BKALbfal.d.ts +0 -223
  713. package/dist/reactive-log-DIGdYqQ6.d.cts +0 -223
  714. package/dist/reactive-map-CEFGp8TK.d.cts +0 -296
  715. package/dist/reactive-map-DS_SIAxv.d.ts +0 -296
  716. package/dist/resilience-6LYQJAC5.js +0 -1
  717. package/dist/sugar-DQjFmVqb.d.cts +0 -399
  718. package/dist/sugar-fhLIE7TT.d.ts +0 -399
  719. package/dist/topology-tree-Bcz27hpF.d.cts +0 -25
  720. package/dist/topology-tree-xvaD0fOX.d.ts +0 -25
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/base/resilience/_internal.ts","../../../src/base/resilience/backoff.ts","../../../src/utils/ai/browser.ts","../../../src/utils/ai/adapters/providers/browser/chrome-nano.ts","../../../src/utils/ai/adapters/providers/browser/webllm.ts","../../../src/utils/ai/adapters/providers/anthropic.ts","../../../src/base/io/http-error.ts","../../../src/base/io/sse.ts","../../../src/utils/ai/adapters/providers/dry-run.ts","../../../src/utils/ai/adapters/providers/fallback.ts","../../../src/utils/ai/adapters/middleware/replay-cache.ts","../../../src/base/composition/single-from-any.ts","../../../src/base/sources/settled.ts","../../../src/utils/ai/adapters/_internal/content-addressed-cache.ts","../../../src/utils/ai/adapters/_internal/wrappers.ts","../../../src/utils/ai/adapters/providers/google.ts","../../../src/utils/ai/adapters/providers/openai-compat.ts","../../../src/utils/ai/adapters/core/factory.ts","../../../src/utils/ai/adapters/routing/cascading.ts","../../../src/utils/resilience/breaker.ts","../../../src/utils/ai/adapters/routing/browser-presets.ts"],"sourcesContent":["/**\n * Internal helpers shared by resilience sub-files.\n *\n * Not part of the public surface. The base-layer resilience operators\n * co-located here (`retry.ts`, `status.ts`, `timeout.ts`) import what they\n * need from this file directly; the utils-layer resilience primitives that\n * stayed in `utils/resilience/` (`breaker.ts`, `rate-limiter.ts`,\n * `fallback.ts`) import it top-down via `../../base/resilience/_internal.js`.\n *\n * `NodeOrValue<T>` is the only export re-surfaced publicly — there is no\n * `base/resilience/index.ts`; it ships through `utils/resilience/index.ts`\n * (and `utils/memory/index.ts`). Every resilience primitive that accepts\n * reactive options uses it as the option-arg shape.\n */\n\nimport type { Node, NodeOptions } from \"@graphrefly/pure-ts/core\";\nimport { DATA, type Message } from \"@graphrefly/pure-ts/core\";\n\nexport type ExtraOpts = Omit<NodeOptions, \"describeKind\">;\n\nexport function operatorOpts<T>(opts?: ExtraOpts): NodeOptions<T> {\n\treturn { describeKind: \"derived\", ...opts } as NodeOptions<T>;\n}\n\nexport function clampNonNegative(value: number): number {\n\treturn value < 0 ? 0 : value;\n}\n\nexport function msgVal(m: Message): unknown {\n\treturn m[1];\n}\n\nexport function coerceDelayNs(raw: number): number {\n\tif (typeof raw !== \"number\" || !Number.isFinite(raw)) {\n\t\tthrow new TypeError(\"backoff strategy must return a finite number\");\n\t}\n\treturn raw < 0 ? 0 : raw;\n}\n\nexport function isNode(x: unknown): x is Node {\n\treturn (\n\t\tx != null &&\n\t\ttypeof x === \"object\" &&\n\t\t\"cache\" in x &&\n\t\ttypeof (x as Node).subscribe === \"function\"\n\t);\n}\n\n/**\n * Either a literal value or a reactive Node carrying it. Mirrors\n * {@link FallbackInput}'s precedent for \"options that may be reactive.\"\n *\n * Used by {@link timeout} / {@link retry} / {@link rateLimiter} /\n * {@link circuitBreaker} / {@link budgetGate} to accept reactive option\n * configurations (Tier 6.5 3.2, 2026-04-29). Each primitive subscribes\n * to the option Node via {@link resolveReactiveOption} and rebinds\n * internal state per its locked swap-semantic rule (see each primitive's\n * JSDoc for the rule).\n *\n * @category extra\n */\nexport type NodeOrValue<T> = T | Node<T>;\n\n/**\n * Closure-mirror helper for `NodeOrValue<T>` options\n * (COMPOSITION-GUIDE §28). Returns:\n * - `current()` — read the latest value (cached at construction; updated\n * on each Node DATA emission).\n * - `unsub()` — release the subscription. Static-form arg never\n * subscribes; `unsub` is a no-op there.\n *\n * `onChange` fires on each DATA after the initial value (skips the\n * cache-seed read). Use to rebind primitive-internal state per the\n * primitive's locked swap-semantic rule.\n *\n * @internal\n */\nexport function resolveReactiveOption<T>(\n\targ: NodeOrValue<T>,\n\tonChange?: (next: T) => void,\n): { current: () => T; unsub: () => void } {\n\tif (!isNode(arg)) {\n\t\treturn { current: () => arg, unsub: () => undefined };\n\t}\n\tconst node = arg as Node<T>;\n\tlet latest: T = node.cache as T;\n\tconst unsub = node.subscribe((msgs) => {\n\t\tfor (const m of msgs) {\n\t\t\tif (m[0] === DATA) {\n\t\t\t\tlatest = m[1] as T;\n\t\t\t\tif (onChange) onChange(latest);\n\t\t\t}\n\t\t}\n\t});\n\treturn {\n\t\tcurrent: () => latest,\n\t\tunsub,\n\t};\n}\n\nexport function isThenable(x: unknown): x is PromiseLike<unknown> {\n\treturn x != null && typeof (x as PromiseLike<unknown>).then === \"function\";\n}\n\nexport function isAsyncIterable(x: unknown): x is AsyncIterable<unknown> {\n\treturn (\n\t\tx != null &&\n\t\ttypeof x === \"object\" &&\n\t\ttypeof (x as AsyncIterable<unknown>)[Symbol.asyncIterator] === \"function\"\n\t);\n}\n","/**\n * Backoff strategies for {@link retry} (roadmap §3.1). Delays are in **nanoseconds**.\n *\n * Convention: all graphrefly-ts timestamps and durations use nanoseconds (`_ns` suffix).\n * 1 second = 1_000_000_000 ns, 1 ms = 1_000_000 ns.\n */\n\nexport const NS_PER_MS = 1_000_000;\nexport const NS_PER_SEC = 1_000_000_000;\n\nexport type JitterMode = \"none\" | \"full\" | \"equal\";\n\nexport type BackoffPreset =\n\t| \"constant\"\n\t| \"linear\"\n\t| \"exponential\"\n\t| \"fibonacci\"\n\t| \"decorrelatedJitter\";\n\n/** `(attempt, error?, previousDelayNs?) => delayNs | null` — `null` means zero delay. */\nexport type BackoffStrategy = (\n\tattempt: number,\n\terror?: unknown,\n\tprevDelayNs?: number | null,\n) => number | null;\n\nfunction clampNonNegative(value: number): number {\n\treturn value < 0 ? 0 : value;\n}\n\nfunction applyJitter(delay: number, jitter: JitterMode): number {\n\tif (jitter === \"none\") return delay;\n\tif (jitter === \"full\") return Math.random() * delay;\n\treturn delay / 2 + Math.random() * (delay / 2);\n}\n\nfunction randomBetween(min: number, max: number): number {\n\treturn min + Math.random() * (max - min);\n}\n\n/**\n * Builds a strategy that always returns the same delay in nanoseconds.\n *\n * @param delayNs - Non-negative delay in nanoseconds; values below zero are clamped to zero.\n * @returns `BackoffStrategy` for use with {@link retry} or custom timers.\n *\n * @example\n * ```ts\n * import { constant, retry, NS_PER_SEC } from \"@graphrefly/graphrefly-ts\";\n *\n * const out = retry(source, { count: 3, backoff: constant(0.25 * NS_PER_SEC) });\n * ```\n *\n * @category extra\n */\nexport function constant(delayNs: number): BackoffStrategy {\n\tconst safe = clampNonNegative(delayNs);\n\treturn () => safe;\n}\n\n/**\n * Builds linear backoff: `baseNs + stepNs * attempt` (`stepNs` defaults to `baseNs`).\n *\n * @param baseNs - Base delay in nanoseconds (clamped non-negative).\n * @param stepNs - Added per retry attempt in nanoseconds (clamped non-negative).\n * @returns `BackoffStrategy` for {@link retry}.\n *\n * @example\n * ```ts\n * import { linear, retry, NS_PER_SEC } from \"@graphrefly/graphrefly-ts\";\n *\n * // Attempt 0 → 1 s, attempt 1 → 2 s, attempt 2 → 3 s …\n * const out = retry(source, { count: 4, backoff: linear(NS_PER_SEC) });\n * ```\n *\n * @category extra\n */\nexport function linear(baseNs: number, stepNs?: number): BackoffStrategy {\n\tconst safeBase = clampNonNegative(baseNs);\n\tconst safeStep = stepNs === undefined ? safeBase : clampNonNegative(stepNs);\n\treturn (attempt: number) => safeBase + safeStep * Math.max(0, attempt);\n}\n\nexport type ExponentialBackoffOptions = {\n\tbaseNs?: number;\n\tfactor?: number;\n\tmaxDelayNs?: number;\n\tjitter?: JitterMode;\n};\n\n/**\n * Builds exponential backoff in nanoseconds, capped by `maxDelayNs`, with optional jitter.\n *\n * @param options - Base, factor, cap, and jitter mode.\n * @returns `BackoffStrategy` for {@link retry}.\n *\n * @remarks\n * **Jitter:** `\"full\"` spreads delay across `[0, delay]`; `\"equal\"` uses `[delay/2, delay]`.\n *\n * @example\n * ```ts\n * import { exponential, retry, NS_PER_SEC } from \"@graphrefly/graphrefly-ts\";\n *\n * // 100 ms → 200 ms → 400 ms … capped at 30 s, with full jitter\n * const out = retry(source, {\n * count: 5,\n * backoff: exponential({ baseNs: 100 * NS_PER_SEC / 1000, jitter: \"full\" }),\n * });\n * ```\n *\n * @category extra\n */\nexport function exponential(options?: ExponentialBackoffOptions): BackoffStrategy {\n\tconst baseNs = clampNonNegative(options?.baseNs ?? 100 * NS_PER_MS);\n\tconst factor = options?.factor !== undefined && options.factor < 1 ? 1 : (options?.factor ?? 2);\n\tconst maxDelayNs = clampNonNegative(options?.maxDelayNs ?? 30 * NS_PER_SEC);\n\tconst jitter = options?.jitter ?? \"none\";\n\n\treturn (attempt: number) => {\n\t\tlet delay: number;\n\t\tif (baseNs === 0) {\n\t\t\tdelay = 0;\n\t\t} else if (factor === 1) {\n\t\t\tdelay = baseNs;\n\t\t} else {\n\t\t\tconst capRatio = maxDelayNs / baseNs;\n\t\t\tlet growth = 1;\n\t\t\tfor (let i = 0; i < Math.max(0, attempt); i++) {\n\t\t\t\tif (growth >= capRatio) {\n\t\t\t\t\tgrowth = capRatio;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tgrowth *= factor;\n\t\t\t}\n\t\t\tdelay = baseNs * growth;\n\t\t\tif (delay > maxDelayNs) delay = maxDelayNs;\n\t\t}\n\t\treturn applyJitter(delay, jitter);\n\t};\n}\n\n/**\n * Builds Fibonacci-scaled delays: `1, 2, 3, 5, … × baseNs`, capped at `maxDelayNs`.\n *\n * @param baseNs - Multiplier applied to the Fibonacci unit (default `100ms` in nanoseconds).\n * @param maxDelayNs - Upper bound in nanoseconds (default `30s`).\n * @returns `BackoffStrategy` for {@link retry}.\n *\n * @example\n * ```ts\n * import { fibonacci, retry, NS_PER_MS } from \"@graphrefly/graphrefly-ts\";\n *\n * // Delays: 100 ms, 200 ms, 300 ms, 500 ms, 800 ms … (× 100 ms base)\n * const out = retry(source, { count: 5, backoff: fibonacci(100 * NS_PER_MS) });\n * ```\n *\n * @category extra\n */\nexport function fibonacci(baseNs = 100 * NS_PER_MS, maxDelayNs = 30 * NS_PER_SEC): BackoffStrategy {\n\tconst safeBase = clampNonNegative(baseNs);\n\tconst safeMax = clampNonNegative(maxDelayNs);\n\n\tfunction fibUnit(attempt: number): number {\n\t\tif (attempt <= 0) return 1;\n\t\tlet prev = 1;\n\t\tlet cur = 2;\n\t\tfor (let i = 1; i < attempt; i++) {\n\t\t\tconst next = prev + cur;\n\t\t\tprev = cur;\n\t\t\tcur = next;\n\t\t}\n\t\treturn cur;\n\t}\n\n\treturn (attempt: number) => {\n\t\tconst raw = fibUnit(attempt) * safeBase;\n\t\treturn raw <= safeMax ? raw : safeMax;\n\t};\n}\n\n/**\n * Decorrelated jitter (AWS-recommended): `random(baseNs, min(maxNs, lastDelay * 3))`.\n *\n * Stateless — uses `prevDelayNs` (passed by the consumer) instead of closure state.\n * Safe to share across concurrent retry sequences.\n *\n * @param baseNs - Floor of the random range (default `100ms` in nanoseconds).\n * @param maxNs - Ceiling cap (default `30s` in nanoseconds).\n * @returns `BackoffStrategy` for {@link retry}.\n *\n * @example\n * ```ts\n * import { decorrelatedJitter, retry, NS_PER_MS, NS_PER_SEC } from \"@graphrefly/graphrefly-ts\";\n *\n * const out = retry(source, {\n * count: 6,\n * backoff: decorrelatedJitter(100 * NS_PER_MS, 10 * NS_PER_SEC),\n * });\n * ```\n *\n * @category extra\n */\nexport function decorrelatedJitter(\n\tbaseNs = 100 * NS_PER_MS,\n\tmaxNs = 30 * NS_PER_SEC,\n): BackoffStrategy {\n\treturn (_attempt, _error, prevDelayNs) => {\n\t\tconst last = prevDelayNs ?? baseNs;\n\t\tconst ceiling = Math.min(maxNs, last * 3);\n\t\treturn randomBetween(baseNs, ceiling);\n\t};\n}\n\n/**\n * Decorator that caps any strategy at `maxAttempts`. Returns `null` (stop retrying) after the cap.\n *\n * @param strategy - Inner strategy to wrap.\n * @param maxAttempts - Maximum number of attempts (inclusive).\n * @returns Wrapped `BackoffStrategy`.\n *\n * @example\n * ```ts\n * import { withMaxAttempts, exponential } from \"@graphrefly/graphrefly-ts\";\n *\n * const capped = withMaxAttempts(exponential(), 3);\n * capped(3); // null — no more retries beyond attempt 3\n * ```\n *\n * @category extra\n */\nexport function withMaxAttempts(strategy: BackoffStrategy, maxAttempts: number): BackoffStrategy {\n\treturn (attempt, error, prevDelayNs) => {\n\t\tif (attempt >= maxAttempts) return null;\n\t\treturn strategy(attempt, error, prevDelayNs);\n\t};\n}\n\n/**\n * Maps a preset name to a concrete {@link BackoffStrategy} with library-default parameters.\n *\n * @param name - One of `constant`, `linear`, `exponential`, `fibonacci`, or `decorrelatedJitter`.\n * @returns Configured strategy with default parameters.\n * @throws Error when `name` is not a known preset.\n *\n * @example\n * ```ts\n * import { resolveBackoffPreset, retry } from \"@graphrefly/graphrefly-ts\";\n *\n * const out = retry(source, { count: 3, backoff: resolveBackoffPreset(\"exponential\") });\n * // Equivalent to retry(source, { count: 3, backoff: exponential() })\n * ```\n *\n * @category extra\n */\nexport function resolveBackoffPreset(name: BackoffPreset): BackoffStrategy {\n\tif (name === \"constant\") return constant(1 * NS_PER_SEC);\n\tif (name === \"linear\") return linear(1 * NS_PER_SEC);\n\tif (name === \"exponential\") return exponential();\n\tif (name === \"fibonacci\") return fibonacci();\n\tif (name === \"decorrelatedJitter\") return decorrelatedJitter();\n\tthrow new Error(\n\t\t`Unknown backoff preset: \"${String(name)}\". Use one of: constant, linear, exponential, fibonacci, decorrelatedJitter`,\n\t);\n}\n","/**\n * Browser-only surface for the AI patterns package.\n *\n * Re-exports browser-native adapters (`webllmAdapter`, `chromeNanoAdapter`)\n * and curated cascade presets that compose them (`cloudFirstPreset`,\n * `localFirstPreset`, `offlinePreset`). Import from\n * `@graphrefly/graphrefly/patterns/ai/browser` in a browser bundle to opt\n * into these; the universal `@graphrefly/graphrefly/patterns/ai` entry does\n * not pull them, so Node bundles stay lean.\n *\n * @module\n */\n\nexport * from \"./adapters/providers/browser/index.js\";\nexport * from \"./adapters/routing/browser-presets.js\";\n","/**\n * ChromeNanoAdapter — Chrome Built-in AI Prompt API.\n *\n * Uses `navigator.ai.languageModel` (Chrome 131+, origin trial / flag gated).\n * Zero download, instant startup — but limited capability (no tool use on\n * most versions, no rich system prompts on some).\n *\n * **Stream mode:** Chrome AI has historically switched between emitting\n * accumulated (each chunk is the full text so far) and delta (each chunk is\n * only the new tokens) streams across versions. Default `streamMode: \"accumulated\"`\n * matches current behavior; pass `\"delta\"` if you've verified your browser\n * emits pure deltas.\n */\n\nimport { monotonicNs } from \"@graphrefly/pure-ts/core\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n\tTokenUsage,\n} from \"../../core/types.js\";\n\nexport interface ChromeNanoAdapterOptions {\n\t/** Override the navigator object (for tests). */\n\tnavigatorOverride?: Navigator;\n\t/** Initial system prompt for the session (Chrome AI supports it in 131+). */\n\tsystemPrompt?: string;\n\t/** Temperature (0..1). */\n\ttemperature?: number;\n\t/** Top-K sampling (Chrome AI only). */\n\ttopK?: number;\n\t/**\n\t * Stream chunk shape. `\"accumulated\"` (default) — each chunk contains the\n\t * full cumulative text; adapter computes deltas by string diffing.\n\t * `\"delta\"` — each chunk already contains only the new tokens; adapter\n\t * forwards directly.\n\t */\n\tstreamMode?: \"accumulated\" | \"delta\";\n}\n\ninterface ChromeAiSession {\n\tprompt(input: string, opts?: { signal?: AbortSignal }): Promise<string>;\n\tpromptStreaming(input: string, opts?: { signal?: AbortSignal }): AsyncIterable<string>;\n\tdestroy?(): void;\n}\n\ninterface ChromeAi {\n\tlanguageModel?: {\n\t\tcreate(params?: {\n\t\t\tsystemPrompt?: string;\n\t\t\ttemperature?: number;\n\t\t\ttopK?: number;\n\t\t\tsignal?: AbortSignal;\n\t\t}): Promise<ChromeAiSession>;\n\t\tcapabilities?(): Promise<{ available?: \"readily\" | \"after-download\" | \"no\" }>;\n\t};\n}\n\nfunction makeAbortError(): Error {\n\tconst err = new Error(\"aborted\") as Error & { name: string };\n\terr.name = \"AbortError\";\n\treturn err;\n}\n\nexport function chromeNanoAdapter(opts: ChromeNanoAdapterOptions = {}): LLMAdapter {\n\tconst streamMode = opts.streamMode ?? \"accumulated\";\n\tconst nav = opts.navigatorOverride ?? (globalThis as { navigator?: Navigator }).navigator;\n\tconst getAi = (): ChromeAi => {\n\t\tconst ai = (nav as unknown as { ai?: ChromeAi })?.ai;\n\t\tif (!ai?.languageModel)\n\t\t\tthrow new Error(\n\t\t\t\t\"chromeNanoAdapter: Chrome AI languageModel not available (requires Chrome 131+ with flag/OT).\",\n\t\t\t);\n\t\treturn ai;\n\t};\n\n\tconst session = async (invokeOpts: LLMInvokeOptions | undefined): Promise<ChromeAiSession> => {\n\t\tconst ai = getAi();\n\t\treturn ai.languageModel!.create({\n\t\t\tsystemPrompt: invokeOpts?.systemPrompt ?? opts.systemPrompt,\n\t\t\ttemperature: invokeOpts?.temperature ?? opts.temperature,\n\t\t\ttopK: opts.topK,\n\t\t\tsignal: invokeOpts?.signal,\n\t\t});\n\t};\n\n\tconst flatten = (messages: readonly ChatMessage[]): string => {\n\t\t// Chrome AI has no multi-message chat API; flatten to a single prompt\n\t\t// with role-tagged sections. Assistant history is preserved as context.\n\t\tconst parts: string[] = [];\n\t\tfor (const m of messages) {\n\t\t\tif (m.role === \"system\") continue; // already passed via systemPrompt\n\t\t\tparts.push(`${m.role}: ${m.content}`);\n\t\t}\n\t\treturn parts.join(\"\\n\\n\");\n\t};\n\n\t// Chrome AI exposes no token count; we leave usage zeroed.\n\tconst zeroUsage = (): TokenUsage => ({ input: { regular: 0 }, output: { regular: 0 } });\n\n\treturn {\n\t\tprovider: \"chrome-nano\",\n\t\tmodel: \"chrome-nano\",\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst sess = await session(invokeOpts);\n\t\t\ttry {\n\t\t\t\tconst prompt = flatten(messages);\n\t\t\t\tconst start = monotonicNs();\n\t\t\t\tconst content = await sess.prompt(prompt, { signal: invokeOpts?.signal });\n\t\t\t\tconst latencyMs = Math.max(0, (monotonicNs() - start) / 1e6);\n\t\t\t\treturn {\n\t\t\t\t\tcontent,\n\t\t\t\t\tusage: zeroUsage(),\n\t\t\t\t\tfinishReason: \"stop\",\n\t\t\t\t\tlatencyMs,\n\t\t\t\t\tmodel: \"chrome-nano\",\n\t\t\t\t\tprovider: \"chrome-nano\",\n\t\t\t\t};\n\t\t\t} finally {\n\t\t\t\tsess.destroy?.();\n\t\t\t}\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst sess = await session(invokeOpts);\n\t\t\ttry {\n\t\t\t\tconst prompt = flatten(messages);\n\t\t\t\tif (streamMode === \"delta\") {\n\t\t\t\t\tfor await (const chunk of sess.promptStreaming(prompt, {\n\t\t\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t\t\t})) {\n\t\t\t\t\t\tif (invokeOpts?.signal?.aborted) throw makeAbortError();\n\t\t\t\t\t\tif (chunk) yield { type: \"token\", delta: chunk };\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlet last = \"\";\n\t\t\t\t\tfor await (const chunk of sess.promptStreaming(prompt, {\n\t\t\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t\t\t})) {\n\t\t\t\t\t\tif (invokeOpts?.signal?.aborted) throw makeAbortError();\n\t\t\t\t\t\t// Accumulated mode: compute the delta against the last cumulative value.\n\t\t\t\t\t\tconst delta = chunk.startsWith(last) ? chunk.slice(last.length) : chunk;\n\t\t\t\t\t\tlast = chunk;\n\t\t\t\t\t\tif (delta) yield { type: \"token\", delta };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tyield { type: \"usage\", usage: zeroUsage() };\n\t\t\t\tyield { type: \"finish\", reason: \"stop\" };\n\t\t\t} finally {\n\t\t\t\tsess.destroy?.();\n\t\t\t}\n\t\t},\n\t};\n}\n","/**\n * WebLLMAdapter — browser-only, WebGPU-based inference via `@mlc-ai/web-llm`.\n *\n * Dynamic import + WebGPU feature detection. No server dependency. Typical\n * use: fallback tier in `cascadingLlmAdapter` after a BYOK cloud adapter.\n */\n\nimport { monotonicNs } from \"@graphrefly/pure-ts/core\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n\tTokenUsage,\n} from \"../../core/types.js\";\n\nexport interface WebLLMAdapterOptions {\n\tmodel: string;\n\t/**\n\t * User-provided engine instance (from `CreateMLCEngine(...)`). If omitted,\n\t * the adapter lazy-creates one on first call via dynamic import.\n\t */\n\tengine?: WebLLMEngineLike;\n\t/** Pass-through to `CreateMLCEngine`. */\n\tinitProgressCallback?: (progress: unknown) => void;\n\t/** Navigator override (for tests). */\n\tnavigatorOverride?: Navigator;\n}\n\nexport interface WebLLMEngineLike {\n\tchat: {\n\t\tcompletions: {\n\t\t\tcreate(\n\t\t\t\tparams: Record<string, unknown>,\n\t\t\t\topts?: { signal?: AbortSignal },\n\t\t\t): Promise<{\n\t\t\t\tchoices: ReadonlyArray<{ message?: { content?: string }; finish_reason?: string }>;\n\t\t\t\tusage?: { prompt_tokens?: number; completion_tokens?: number };\n\t\t\t}>;\n\t\t};\n\t};\n}\n\nfunction makeAbortError(): Error {\n\tconst err = new Error(\"aborted\") as Error & { name: string };\n\terr.name = \"AbortError\";\n\treturn err;\n}\n\nexport function webllmAdapter(opts: WebLLMAdapterOptions): LLMAdapter {\n\tlet engine = opts.engine;\n\n\tconst ensureEngine = async (): Promise<WebLLMEngineLike> => {\n\t\tif (engine) return engine;\n\t\tif (!isWebGpuAvailable(opts.navigatorOverride))\n\t\t\tthrow new Error(\"webllmAdapter: WebGPU not available in this environment\");\n\t\tconst mod = await import(\"@mlc-ai/web-llm\" as string).catch(() => {\n\t\t\tthrow new Error(\n\t\t\t\t\"webllmAdapter: @mlc-ai/web-llm not installed. Add it as a peer dependency or pass opts.engine.\",\n\t\t\t);\n\t\t});\n\t\tconst factory = (\n\t\t\tmod as { CreateMLCEngine?: (m: string, o?: unknown) => Promise<WebLLMEngineLike> }\n\t\t).CreateMLCEngine;\n\t\tif (!factory) throw new Error(\"webllmAdapter: @mlc-ai/web-llm missing CreateMLCEngine export\");\n\t\tengine = await factory(opts.model, { initProgressCallback: opts.initProgressCallback });\n\t\treturn engine;\n\t};\n\n\tconst flatten = (\n\t\tmessages: readonly ChatMessage[],\n\t\tinvokeOpts: LLMInvokeOptions | undefined,\n\t): Array<{ role: string; content: string }> => {\n\t\tconst flat: Array<{ role: string; content: string }> = [];\n\t\tif (invokeOpts?.systemPrompt) flat.push({ role: \"system\", content: invokeOpts.systemPrompt });\n\t\tfor (const m of messages)\n\t\t\tflat.push({ role: m.role === \"tool\" ? \"user\" : m.role, content: m.content });\n\t\treturn flat;\n\t};\n\n\tconst mapUsage = (\n\t\tu: { prompt_tokens?: number; completion_tokens?: number } | undefined,\n\t): TokenUsage => ({\n\t\tinput: { regular: u?.prompt_tokens ?? 0 },\n\t\toutput: { regular: u?.completion_tokens ?? 0 },\n\t\traw: u,\n\t});\n\n\treturn {\n\t\tprovider: \"webllm\",\n\t\tmodel: opts.model,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst eng = await ensureEngine();\n\t\t\tconst start = monotonicNs();\n\t\t\tconst resp = await eng.chat.completions.create(\n\t\t\t\t{\n\t\t\t\t\tmodel: invokeOpts?.model ?? opts.model,\n\t\t\t\t\tmessages: flatten(messages, invokeOpts),\n\t\t\t\t\tmax_tokens: invokeOpts?.maxTokens,\n\t\t\t\t\ttemperature: invokeOpts?.temperature,\n\t\t\t\t},\n\t\t\t\t{ signal: invokeOpts?.signal },\n\t\t\t);\n\t\t\tconst latencyMs = Math.max(0, (monotonicNs() - start) / 1e6);\n\t\t\tconst choice = resp.choices?.[0];\n\t\t\treturn {\n\t\t\t\tcontent: choice?.message?.content ?? \"\",\n\t\t\t\tusage: mapUsage(resp.usage),\n\t\t\t\tfinishReason: choice?.finish_reason,\n\t\t\t\tlatencyMs,\n\t\t\t\tmodel: opts.model,\n\t\t\t\tprovider: \"webllm\",\n\t\t\t};\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst eng = await ensureEngine();\n\t\t\tconst asyncIter = (await eng.chat.completions.create(\n\t\t\t\t{\n\t\t\t\t\tmodel: invokeOpts?.model ?? opts.model,\n\t\t\t\t\tmessages: flatten(messages, invokeOpts),\n\t\t\t\t\tmax_tokens: invokeOpts?.maxTokens,\n\t\t\t\t\ttemperature: invokeOpts?.temperature,\n\t\t\t\t\tstream: true,\n\t\t\t\t},\n\t\t\t\t{ signal: invokeOpts?.signal },\n\t\t\t)) as unknown as AsyncIterable<{\n\t\t\t\tchoices?: ReadonlyArray<{ delta?: { content?: string }; finish_reason?: string }>;\n\t\t\t\tusage?: { prompt_tokens?: number; completion_tokens?: number };\n\t\t\t}>;\n\n\t\t\tlet finalUsage: { prompt_tokens?: number; completion_tokens?: number } | undefined;\n\t\t\tlet finishReason: string | undefined;\n\t\t\tfor await (const chunk of asyncIter) {\n\t\t\t\tif (invokeOpts?.signal?.aborted) throw makeAbortError();\n\t\t\t\tconst c = chunk.choices?.[0];\n\t\t\t\tif (c?.delta?.content) yield { type: \"token\", delta: c.delta.content };\n\t\t\t\tif (c?.finish_reason) finishReason = c.finish_reason;\n\t\t\t\tif (chunk.usage) finalUsage = chunk.usage;\n\t\t\t}\n\t\t\tif (finalUsage) yield { type: \"usage\", usage: mapUsage(finalUsage) };\n\t\t\tyield { type: \"finish\", reason: finishReason ?? \"stop\" };\n\t\t},\n\t};\n}\n\nfunction isWebGpuAvailable(navOverride?: Navigator): boolean {\n\tconst nav = navOverride ?? (globalThis as { navigator?: Navigator }).navigator;\n\treturn !!(nav && \"gpu\" in nav && (nav as unknown as { gpu?: unknown }).gpu);\n}\n","/**\n * AnthropicAdapter — default fetch-backed, optional SDK-backed.\n *\n * - `anthropicAdapter({ apiKey })` uses native `fetch` + SSE parsing.\n * - `anthropicAdapter({ sdk })` delegates to a user-provided `@anthropic-ai/sdk` instance.\n *\n * Token usage mapping:\n * - `input_tokens` → `input.regular`\n * - `cache_read_input_tokens` → `input.cacheRead`\n * - `cache_creation.ephemeral_5m_input_tokens` → `input.cacheWrite5m`\n * - `cache_creation.ephemeral_1h_input_tokens` → `input.cacheWrite1h`\n * - `cache_creation_input_tokens` (legacy) → `input.cacheWrite5m` (default TTL)\n * - `output_tokens` → `output.regular`\n * - `server_tool_use.web_search_requests` → `auxiliary.webSearchRequests`\n */\n\nimport { monotonicNs } from \"@graphrefly/pure-ts/core\";\nimport { makeHttpError } from \"../../../../base/io/http-error.js\";\nimport { parseSSEStream } from \"../../../../base/io/sse.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n\tTokenUsage,\n\tToolDefinition,\n} from \"../core/types.js\";\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface AnthropicAdapterOptions {\n\t/** API key. Falls back to `process.env.ANTHROPIC_API_KEY` on Node. */\n\tapiKey?: string;\n\t/** Default model (overridable per-call via `LLMInvokeOptions.model`). */\n\tmodel?: string;\n\t/** Override the base URL. Default `https://api.anthropic.com`. */\n\tbaseURL?: string;\n\t/** API version header. Default `\"2023-06-01\"`. */\n\tanthropicVersion?: string;\n\t/** Additional headers to send on every request (overridden by per-call). */\n\theaders?: Record<string, string>;\n\t/**\n\t * User-provided SDK instance. When present, the adapter delegates to it\n\t * (uses `.messages.create`) instead of native fetch.\n\t * Shape matches `@anthropic-ai/sdk` `.messages` API; any object with a\n\t * compatible `create`/`stream` contract works.\n\t */\n\tsdk?: AnthropicSdkLike;\n\t/** Custom fetch (useful for tests). Default `globalThis.fetch`. */\n\tfetchImpl?: typeof fetch;\n}\n\n/** Minimal SDK shape we interoperate with. */\nexport interface AnthropicSdkLike {\n\tmessages: {\n\t\tcreate(\n\t\t\tparams: Record<string, unknown>,\n\t\t\topts?: { signal?: AbortSignal },\n\t\t): Promise<AnthropicMessageResponse>;\n\t\tstream?(\n\t\t\tparams: Record<string, unknown>,\n\t\t\topts?: { signal?: AbortSignal },\n\t\t): AsyncIterable<AnthropicStreamEvent>;\n\t};\n}\n\ninterface AnthropicMessageResponse {\n\tid: string;\n\tcontent: ReadonlyArray<\n\t\t| { type: \"text\"; text: string }\n\t\t| { type: \"tool_use\"; id: string; name: string; input: Record<string, unknown> }\n\t\t| { type: \"thinking\"; thinking: string }\n\t\t| { type: string; [key: string]: unknown }\n\t>;\n\tstop_reason?: string;\n\tusage: AnthropicUsage;\n\tmodel?: string;\n}\n\ninterface AnthropicUsage {\n\tinput_tokens?: number;\n\toutput_tokens?: number;\n\tcache_read_input_tokens?: number;\n\tcache_creation_input_tokens?: number;\n\tcache_creation?: {\n\t\tephemeral_5m_input_tokens?: number;\n\t\tephemeral_1h_input_tokens?: number;\n\t};\n\tserver_tool_use?: {\n\t\tweb_search_requests?: number;\n\t};\n}\n\ntype AnthropicStreamEvent =\n\t| { type: \"message_start\"; message: { usage: AnthropicUsage } }\n\t| { type: \"content_block_start\"; index: number; content_block: Record<string, unknown> }\n\t| { type: \"content_block_delta\"; index: number; delta: Record<string, unknown> }\n\t| { type: \"content_block_stop\"; index: number }\n\t| { type: \"message_delta\"; delta: { stop_reason?: string; usage?: AnthropicUsage } }\n\t| { type: \"message_stop\" }\n\t| { type: string; [key: string]: unknown };\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function anthropicAdapter(opts: AnthropicAdapterOptions = {}): LLMAdapter {\n\tif (opts.sdk) return sdkBackedAnthropic(opts);\n\treturn fetchBackedAnthropic(opts);\n}\n\n// ---------------------------------------------------------------------------\n// Request/response mapping\n// ---------------------------------------------------------------------------\n\nfunction toAnthropicRequest(\n\tmessages: readonly ChatMessage[],\n\tinvokeOpts: LLMInvokeOptions | undefined,\n\tdefaultModel: string | undefined,\n\tstream: boolean,\n): Record<string, unknown> {\n\tconst model = invokeOpts?.model ?? defaultModel;\n\tif (!model)\n\t\tthrow new Error(\"anthropicAdapter: model must be set via options.model or invokeOpts.model\");\n\n\tconst { system, chat } = partitionSystem(messages, invokeOpts?.systemPrompt);\n\n\tconst body: Record<string, unknown> = {\n\t\tmodel,\n\t\tmessages: chat.map(toAnthropicMessage),\n\t\tmax_tokens: invokeOpts?.maxTokens ?? 4096,\n\t};\n\tif (system) body.system = system;\n\tif (invokeOpts?.temperature != null) body.temperature = invokeOpts.temperature;\n\tif (invokeOpts?.tools && invokeOpts.tools.length > 0)\n\t\tbody.tools = invokeOpts.tools.map(toAnthropicTool);\n\tif (invokeOpts?.maxReasoningTokens != null) {\n\t\tbody.thinking = { type: \"enabled\", budget_tokens: invokeOpts.maxReasoningTokens };\n\t}\n\tif (invokeOpts?.cacheHint) {\n\t\t// Cache-control injected per-message by the user (Anthropic cache is\n\t\t// block-level). We surface the hint via metadata, but the canonical\n\t\t// cacheHint API is informational — power users pass cache_control\n\t\t// directly on messages via providerExtras.\n\t}\n\tif (stream) body.stream = true;\n\tif (invokeOpts?.providerExtras) Object.assign(body, invokeOpts.providerExtras);\n\treturn body;\n}\n\nfunction partitionSystem(\n\tmessages: readonly ChatMessage[],\n\tsystemPrompt: string | undefined,\n): { system: string | undefined; chat: readonly ChatMessage[] } {\n\tconst systemParts: string[] = [];\n\tif (systemPrompt) systemParts.push(systemPrompt);\n\tconst chat: ChatMessage[] = [];\n\tfor (const m of messages) {\n\t\tif (m.role === \"system\") systemParts.push(m.content);\n\t\telse chat.push(m);\n\t}\n\treturn { system: systemParts.length > 0 ? systemParts.join(\"\\n\\n\") : undefined, chat };\n}\n\nfunction toAnthropicMessage(m: ChatMessage): Record<string, unknown> {\n\tif (m.role === \"tool\") {\n\t\treturn {\n\t\t\trole: \"user\",\n\t\t\tcontent: [\n\t\t\t\t{\n\t\t\t\t\ttype: \"tool_result\",\n\t\t\t\t\ttool_use_id: m.toolCallId,\n\t\t\t\t\tcontent: m.content,\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n\tif (m.role === \"assistant\" && m.toolCalls && m.toolCalls.length > 0) {\n\t\tconst blocks: unknown[] = [];\n\t\tif (m.content) blocks.push({ type: \"text\", text: m.content });\n\t\tfor (const tc of m.toolCalls) {\n\t\t\tblocks.push({ type: \"tool_use\", id: tc.id, name: tc.name, input: tc.arguments });\n\t\t}\n\t\treturn { role: \"assistant\", content: blocks };\n\t}\n\treturn { role: m.role, content: m.content };\n}\n\nfunction toAnthropicTool(t: ToolDefinition): Record<string, unknown> {\n\treturn {\n\t\tname: t.name,\n\t\tdescription: t.description,\n\t\tinput_schema: t.parameters,\n\t};\n}\n\n/**\n * Merge an incoming Anthropic usage update into the running snapshot. Unlike\n * a shallow spread, this preserves nested `cache_creation` fields when the\n * update omits them (or sends an empty object). Applied to both SSE and SDK\n * streaming paths.\n */\nfunction mergeAnthropicUsage(\n\tprev: AnthropicUsage | undefined,\n\tnext: AnthropicUsage,\n): AnthropicUsage {\n\tif (!prev) return { ...next };\n\tconst merged: AnthropicUsage = { ...prev };\n\t// Scalar fields: overwrite when present in `next`.\n\tif (next.input_tokens != null) merged.input_tokens = next.input_tokens;\n\tif (next.output_tokens != null) merged.output_tokens = next.output_tokens;\n\tif (next.cache_read_input_tokens != null)\n\t\tmerged.cache_read_input_tokens = next.cache_read_input_tokens;\n\tif (next.cache_creation_input_tokens != null)\n\t\tmerged.cache_creation_input_tokens = next.cache_creation_input_tokens;\n\t// Nested `cache_creation`: shallow-merge its own fields so a non-empty\n\t// update doesn't wipe a prior ephemeral_5m/1h value.\n\tif (next.cache_creation) {\n\t\tmerged.cache_creation = {\n\t\t\t...(prev.cache_creation ?? {}),\n\t\t\t...next.cache_creation,\n\t\t};\n\t}\n\tif (next.server_tool_use) {\n\t\tmerged.server_tool_use = {\n\t\t\t...(prev.server_tool_use ?? {}),\n\t\t\t...next.server_tool_use,\n\t\t};\n\t}\n\treturn merged;\n}\n\nfunction mapUsage(u: AnthropicUsage | undefined): TokenUsage {\n\tconst usage: TokenUsage = {\n\t\tinput: { regular: u?.input_tokens ?? 0 },\n\t\toutput: { regular: u?.output_tokens ?? 0 },\n\t\traw: u,\n\t};\n\tif (u?.cache_read_input_tokens) usage.input.cacheRead = u.cache_read_input_tokens;\n\tif (u?.cache_creation) {\n\t\tif (u.cache_creation.ephemeral_5m_input_tokens)\n\t\t\tusage.input.cacheWrite5m = u.cache_creation.ephemeral_5m_input_tokens;\n\t\tif (u.cache_creation.ephemeral_1h_input_tokens)\n\t\t\tusage.input.cacheWrite1h = u.cache_creation.ephemeral_1h_input_tokens;\n\t} else if (u?.cache_creation_input_tokens) {\n\t\t// Legacy flat field — default to 5m TTL.\n\t\tusage.input.cacheWrite5m = u.cache_creation_input_tokens;\n\t}\n\tif (u?.server_tool_use?.web_search_requests) {\n\t\tusage.auxiliary = { webSearchRequests: u.server_tool_use.web_search_requests };\n\t}\n\treturn usage;\n}\n\nfunction toLLMResponse(msg: AnthropicMessageResponse, latencyMs: number): LLMResponse {\n\tconst textParts: string[] = [];\n\tconst toolCalls: { id: string; name: string; arguments: Record<string, unknown> }[] = [];\n\tfor (const block of msg.content) {\n\t\tif (block.type === \"text\" && typeof (block as { text?: unknown }).text === \"string\") {\n\t\t\ttextParts.push((block as { text: string }).text);\n\t\t} else if (block.type === \"tool_use\") {\n\t\t\tconst tb = block as { id: string; name: string; input: Record<string, unknown> };\n\t\t\ttoolCalls.push({ id: tb.id, name: tb.name, arguments: tb.input ?? {} });\n\t\t}\n\t}\n\treturn {\n\t\tcontent: textParts.join(\"\"),\n\t\ttoolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n\t\tusage: mapUsage(msg.usage),\n\t\tfinishReason: msg.stop_reason,\n\t\tlatencyMs,\n\t\tmodel: msg.model,\n\t\tprovider: \"anthropic\",\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Fetch-backed impl\n// ---------------------------------------------------------------------------\n\nfunction fetchBackedAnthropic(opts: AnthropicAdapterOptions): LLMAdapter {\n\tconst apiKey =\n\t\topts.apiKey ??\n\t\t(globalThis as { process?: { env?: Record<string, string> } }).process?.env?.ANTHROPIC_API_KEY;\n\tif (!apiKey) {\n\t\t// Don't throw at construction — allow test harnesses / dry-run setups\n\t\t// that never call invoke. Throw at first use instead.\n\t}\n\tconst baseURL = opts.baseURL ?? \"https://api.anthropic.com\";\n\tconst anthropicVersion = opts.anthropicVersion ?? \"2023-06-01\";\n\tconst fetchImpl = opts.fetchImpl ?? fetch;\n\n\tconst commonHeaders = (): Record<string, string> => {\n\t\tif (!apiKey)\n\t\t\tthrow new Error(\"anthropicAdapter: apiKey required for invoke/stream (or provide opts.sdk)\");\n\t\treturn {\n\t\t\t\"x-api-key\": apiKey,\n\t\t\t\"anthropic-version\": anthropicVersion,\n\t\t\t\"content-type\": \"application/json\",\n\t\t\t...(opts.headers ?? {}),\n\t\t};\n\t};\n\n\treturn {\n\t\tprovider: \"anthropic\",\n\t\tmodel: opts.model,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst body = toAnthropicRequest(messages, invokeOpts, opts.model, false);\n\t\t\tconst start = monotonicNs();\n\t\t\tconst resp = await fetchImpl(`${baseURL}/v1/messages`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: commonHeaders(),\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t});\n\t\t\tif (!resp.ok) throw await makeHttpError(resp, \"Anthropic\");\n\t\t\tconst json = (await resp.json()) as AnthropicMessageResponse;\n\t\t\tconst latencyMs = Math.max(0, (monotonicNs() - start) / 1e6);\n\t\t\treturn toLLMResponse(json, latencyMs);\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst body = toAnthropicRequest(messages, invokeOpts, opts.model, true);\n\t\t\tconst resp = await fetchImpl(`${baseURL}/v1/messages`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { ...commonHeaders(), accept: \"text/event-stream\" },\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t});\n\t\t\tif (!resp.ok) throw await makeHttpError(resp, \"Anthropic\");\n\t\t\tif (!resp.body) throw new Error(\"anthropicAdapter: streaming response has no body\");\n\n\t\t\tlet finalUsage: AnthropicUsage | undefined;\n\t\t\tlet finishReason: string | undefined;\n\t\t\tconst toolCallsByIndex: Map<number, { id: string; name: string; argBuf: string }> = new Map();\n\n\t\t\tfor await (const event of parseSSEStream(resp.body, { signal: invokeOpts?.signal })) {\n\t\t\t\tconst data = event.data;\n\t\t\t\tif (!data) continue;\n\t\t\t\tlet parsed: AnthropicStreamEvent;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = JSON.parse(data) as AnthropicStreamEvent;\n\t\t\t\t} catch {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tswitch (parsed.type) {\n\t\t\t\t\tcase \"message_start\": {\n\t\t\t\t\t\tconst ms = parsed as { message: { usage: AnthropicUsage } };\n\t\t\t\t\t\tfinalUsage = mergeAnthropicUsage(finalUsage, ms.message.usage);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"content_block_start\": {\n\t\t\t\t\t\tconst cb = parsed as { index: number; content_block: Record<string, unknown> };\n\t\t\t\t\t\tconst b = cb.content_block;\n\t\t\t\t\t\tif (b.type === \"tool_use\") {\n\t\t\t\t\t\t\ttoolCallsByIndex.set(cb.index, {\n\t\t\t\t\t\t\t\tid: String(b.id ?? \"\"),\n\t\t\t\t\t\t\t\tname: String(b.name ?? \"\"),\n\t\t\t\t\t\t\t\targBuf: \"\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: \"tool-call-delta\",\n\t\t\t\t\t\t\t\tdelta: { id: String(b.id ?? \"\"), name: String(b.name ?? \"\") },\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"content_block_delta\": {\n\t\t\t\t\t\tconst cbd = parsed as { index: number; delta: Record<string, unknown> };\n\t\t\t\t\t\tconst d = cbd.delta;\n\t\t\t\t\t\tif (d.type === \"text_delta\" && typeof d.text === \"string\") {\n\t\t\t\t\t\t\tyield { type: \"token\", delta: d.text };\n\t\t\t\t\t\t} else if (d.type === \"input_json_delta\" && typeof d.partial_json === \"string\") {\n\t\t\t\t\t\t\tconst existing = toolCallsByIndex.get(cbd.index);\n\t\t\t\t\t\t\tif (existing) existing.argBuf += d.partial_json;\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: \"tool-call-delta\",\n\t\t\t\t\t\t\t\tdelta: { argumentsDelta: d.partial_json },\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else if (d.type === \"thinking_delta\" && typeof d.thinking === \"string\") {\n\t\t\t\t\t\t\tyield { type: \"thinking\", delta: d.thinking };\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"message_delta\": {\n\t\t\t\t\t\tconst md = parsed as { delta: { stop_reason?: string; usage?: AnthropicUsage } };\n\t\t\t\t\t\tif (md.delta.stop_reason) finishReason = md.delta.stop_reason;\n\t\t\t\t\t\tif (md.delta.usage) {\n\t\t\t\t\t\t\tfinalUsage = mergeAnthropicUsage(finalUsage, md.delta.usage);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"message_stop\":\n\t\t\t\t\t\t// Fall through to finalize after the loop.\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (finalUsage) yield { type: \"usage\", usage: mapUsage(finalUsage) };\n\t\t\tyield { type: \"finish\", reason: finishReason ?? \"stop\" };\n\t\t},\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// SDK-backed impl\n// ---------------------------------------------------------------------------\n\nfunction sdkBackedAnthropic(opts: AnthropicAdapterOptions): LLMAdapter {\n\tconst sdk = opts.sdk;\n\tif (!sdk) throw new Error(\"sdkBackedAnthropic: sdk instance required\");\n\treturn {\n\t\tprovider: \"anthropic\",\n\t\tmodel: opts.model,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst body = toAnthropicRequest(messages, invokeOpts, opts.model, false);\n\t\t\tconst start = monotonicNs();\n\t\t\tconst resp = (await sdk.messages.create(body, {\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t})) as AnthropicMessageResponse;\n\t\t\tconst latencyMs = Math.max(0, (monotonicNs() - start) / 1e6);\n\t\t\treturn toLLMResponse(resp, latencyMs);\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tif (!sdk.messages.stream) {\n\t\t\t\tthrow new Error(\"sdkBackedAnthropic: SDK instance does not expose .messages.stream\");\n\t\t\t}\n\t\t\tconst body = toAnthropicRequest(messages, invokeOpts, opts.model, true);\n\t\t\tlet finalUsage: AnthropicUsage | undefined;\n\t\t\tlet finishReason: string | undefined;\n\t\t\tfor await (const event of sdk.messages.stream(body, { signal: invokeOpts?.signal })) {\n\t\t\t\tswitch (event.type) {\n\t\t\t\t\tcase \"message_start\":\n\t\t\t\t\t\tfinalUsage = mergeAnthropicUsage(\n\t\t\t\t\t\t\tfinalUsage,\n\t\t\t\t\t\t\t(event as { message: { usage: AnthropicUsage } }).message.usage,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"content_block_delta\": {\n\t\t\t\t\t\tconst d = (event as { delta: Record<string, unknown> }).delta;\n\t\t\t\t\t\tif (d?.type === \"text_delta\" && typeof d.text === \"string\") {\n\t\t\t\t\t\t\tyield { type: \"token\", delta: d.text };\n\t\t\t\t\t\t} else if (d?.type === \"input_json_delta\" && typeof d.partial_json === \"string\") {\n\t\t\t\t\t\t\tyield { type: \"tool-call-delta\", delta: { argumentsDelta: d.partial_json } };\n\t\t\t\t\t\t} else if (d?.type === \"thinking_delta\" && typeof d.thinking === \"string\") {\n\t\t\t\t\t\t\tyield { type: \"thinking\", delta: d.thinking };\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"message_delta\": {\n\t\t\t\t\t\tconst md = event as { delta: { stop_reason?: string; usage?: AnthropicUsage } };\n\t\t\t\t\t\tif (md.delta.stop_reason) finishReason = md.delta.stop_reason;\n\t\t\t\t\t\tif (md.delta.usage) finalUsage = mergeAnthropicUsage(finalUsage, md.delta.usage);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (finalUsage) yield { type: \"usage\", usage: mapUsage(finalUsage) };\n\t\t\tyield { type: \"finish\", reason: finishReason ?? \"stop\" };\n\t\t},\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// SSE parser\n// ---------------------------------------------------------------------------\n","/**\n * HTTP error builder — companion to {@link ./adapters.ts}'s `fromHTTP` /\n * `fromHTTPStream` / `toHTTP`. Pure, zero-dep function that turns a failed\n * `Response` into an `Error` exposing the `{status, headers, message}` shape\n * that `HttpErrorLike` consumers (rate-limit parsers, retry predicates,\n * observability layers) expect.\n *\n * Universal tier — safe for browser and Node. No Node-only imports.\n */\n\n/**\n * Construct an `Error` carrying `status` + `headers` fields from a non-ok\n * `Response`. Reads the body with `resp.text()` for diagnostic context; a\n * body read failure is swallowed (empty string) so the returned error always\n * reflects the original status/statusText at minimum.\n *\n * @param resp - The offending `Response` object.\n * @param provider - Optional prefix (e.g. `\"Anthropic\"`, `\"openai\"`) used in\n * the error message. Defaults to `\"HTTP\"`.\n * @returns An `Error` whose `message` is `\"${provider} API <status>: <statusText>[ — body]\"`,\n * with `status: number` and `headers: Headers` attached.\n *\n * @category extra\n */\nexport async function makeHttpError(resp: Response, provider?: string): Promise<Error> {\n\tlet body: string;\n\ttry {\n\t\tbody = await resp.text();\n\t} catch {\n\t\tbody = \"\";\n\t}\n\tconst prefix = provider ?? \"HTTP\";\n\tconst err = new Error(\n\t\t`${prefix} API ${resp.status}: ${resp.statusText}${body ? ` — ${body}` : \"\"}`,\n\t) as Error & {\n\t\tstatus: number;\n\t\theaders: Headers;\n\t};\n\terr.status = resp.status;\n\terr.headers = resp.headers;\n\treturn err;\n}\n","/**\n * Server-Sent Events IO — `toSSE` / `toSSEBytes` (encode any node into the\n * `text/event-stream` wire format), `toReadableStream` (web-stream sink),\n * `parseSSEStream` (async-iterator parser), `fromSSE` (line-delimited parser\n * source).\n */\n\nimport {\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tdefaultConfig,\n\tERROR,\n\ttype Node,\n\tnode,\n\tRESOLVED,\n} from \"@graphrefly/pure-ts/core\";\nimport { type ExtraOpts, sourceOpts } from \"./_internal.js\";\n\n/** Options for {@link toSSE}. */\nexport type ToSSEOptions = {\n\t/** Custom payload serializer for non-string payloads. Default: `JSON.stringify` fallback to `String(value)`. */\n\tserialize?: (value: unknown) => string;\n\t/** Event name for DATA tuples. Default: `\"data\"`. */\n\tdataEvent?: string;\n\t/** Event name for ERROR tuples. Default: `\"error\"`. */\n\terrorEvent?: string;\n\t/** Event name for COMPLETE tuples. Default: `\"complete\"`. */\n\tcompleteEvent?: string;\n\t/** Emit `event: resolved` when RESOLVED arrives. Default: `false`. */\n\tincludeResolved?: boolean;\n\t/** Emit `event: dirty` when DIRTY arrives. Default: `false`. */\n\tincludeDirty?: boolean;\n\t/** Add SSE comment keepalive frames (`: keepalive`) on an interval. Disabled when unset. */\n\tkeepAliveMs?: number;\n\t/** Optional abort signal to terminate the stream early. */\n\tsignal?: AbortSignal;\n\t/** Maps custom message types to SSE event names. */\n\teventNameResolver?: (type: symbol) => string;\n};\n\nfunction messageTypeLabel(t: symbol): string {\n\treturn Symbol.keyFor(t) ?? t.description ?? \"message\";\n}\n\nfunction serializeSseData(value: unknown, serialize: (value: unknown) => string): string {\n\tif (typeof value === \"string\") return value;\n\treturn serialize(value);\n}\n\nfunction sseFrame(event: string, data?: string): string {\n\tlet out = `event: ${event}\\n`;\n\tif (data !== undefined) {\n\t\tconst lines = data.split(/\\r?\\n/);\n\t\tfor (const line of lines) {\n\t\t\tout += `data: ${line}\\n`;\n\t\t}\n\t}\n\treturn `${out}\\n`;\n}\n\n/**\n * Creates a standard Server-Sent Events stream from node messages.\n *\n * @category extra\n */\nexport function toSSE<T>(source: Node<T>, opts?: ToSSEOptions): ReadableStream<Uint8Array> {\n\tconst {\n\t\tserialize = (value: unknown) => {\n\t\t\tif (value instanceof Error) return value.message;\n\t\t\ttry {\n\t\t\t\treturn JSON.stringify(value);\n\t\t\t} catch {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t},\n\t\tdataEvent = \"data\",\n\t\terrorEvent = \"error\",\n\t\tcompleteEvent = \"complete\",\n\t\tincludeResolved = false,\n\t\tincludeDirty = false,\n\t\tkeepAliveMs,\n\t\tsignal,\n\t\teventNameResolver = messageTypeLabel,\n\t} = opts ?? {};\n\tconst encoder = new TextEncoder();\n\tlet stop: (() => void) | undefined;\n\n\treturn new ReadableStream<Uint8Array>({\n\t\tstart(controller) {\n\t\t\tlet closed = false;\n\t\t\tlet keepAlive: ReturnType<typeof setInterval> | undefined;\n\t\t\tlet unsub: () => void = () => {};\n\t\t\tconst close = () => {\n\t\t\t\tif (closed) return;\n\t\t\t\tclosed = true;\n\t\t\t\tif (keepAlive !== undefined) clearInterval(keepAlive);\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\tunsub();\n\t\t\t\tcontroller.close();\n\t\t\t};\n\t\t\tstop = close;\n\t\t\tconst write = (event: string, data?: string) => {\n\t\t\t\tif (closed) return;\n\t\t\t\tcontroller.enqueue(encoder.encode(sseFrame(event, data)));\n\t\t\t};\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (closed) return;\n\t\t\t\tclose();\n\t\t\t};\n\t\t\tunsub = source.subscribe((msgs) => {\n\t\t\t\tfor (const msg of msgs) {\n\t\t\t\t\tconst t = msg[0];\n\t\t\t\t\t// Skip graph-local signals (tier < 3: START, DIRTY, INVALIDATE,\n\t\t\t\t\t// PAUSE, RESUME). DIRTY is opt-in for observability.\n\t\t\t\t\tif (defaultConfig.isLocalOnly(t)) {\n\t\t\t\t\t\tif (t === DIRTY && includeDirty) {\n\t\t\t\t\t\t\t/* fall through to write */\n\t\t\t\t\t\t} else continue;\n\t\t\t\t\t}\n\t\t\t\t\tif (t === DATA) {\n\t\t\t\t\t\twrite(dataEvent, serializeSseData(msg[1], serialize));\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (t === ERROR) {\n\t\t\t\t\t\twrite(errorEvent, serializeSseData(msg[1], serialize));\n\t\t\t\t\t\tclose();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (t === COMPLETE) {\n\t\t\t\t\t\twrite(completeEvent);\n\t\t\t\t\t\tclose();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// RESOLVED (tier 3) is opt-in for observability.\n\t\t\t\t\tif (!includeResolved && t === RESOLVED) continue;\n\t\t\t\t\twrite(\n\t\t\t\t\t\teventNameResolver(t),\n\t\t\t\t\t\tmsg.length > 1 ? serializeSseData(msg[1], serialize) : undefined,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (keepAliveMs !== undefined && keepAliveMs > 0) {\n\t\t\t\tkeepAlive = setInterval(() => {\n\t\t\t\t\tif (closed) return;\n\t\t\t\t\tcontroller.enqueue(encoder.encode(\": keepalive\\n\\n\"));\n\t\t\t\t}, keepAliveMs);\n\t\t\t}\n\t\t\tif (signal?.aborted) onAbort();\n\t\t\telse signal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t},\n\t\tcancel() {\n\t\t\tstop?.();\n\t\t},\n\t});\n}\n\n/**\n * Composable variant of {@link toSSE} — emits encoded SSE frames as\n * `Uint8Array` through a reactive `Node`. Use this when you want to pipe SSE\n * bytes through the reactive graph (persist to file, tee to multiple streams,\n * etc.). Wrap with {@link toReadableStream} to expose a `ReadableStream` for\n * `new Response(...)` use cases.\n *\n * @category extra\n */\nexport function toSSEBytes<T>(source: Node<T>, opts?: ToSSEOptions): Node<Uint8Array> {\n\tconst {\n\t\tserialize = (value: unknown) => {\n\t\t\tif (value instanceof Error) return value.message;\n\t\t\ttry {\n\t\t\t\treturn JSON.stringify(value);\n\t\t\t} catch {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t},\n\t\tdataEvent = \"data\",\n\t\terrorEvent = \"error\",\n\t\tcompleteEvent = \"complete\",\n\t\tincludeResolved = false,\n\t\tincludeDirty = false,\n\t\tkeepAliveMs,\n\t\tsignal,\n\t\teventNameResolver = messageTypeLabel,\n\t} = opts ?? {};\n\tconst encoder = new TextEncoder();\n\treturn node<Uint8Array>([], (_data, a) => {\n\t\tlet active = true;\n\t\tlet keepAlive: ReturnType<typeof setInterval> | undefined;\n\t\tconst emitFrame = (event: string, data?: string) => {\n\t\t\tif (!active) return;\n\t\t\ta.emit(encoder.encode(sseFrame(event, data)));\n\t\t};\n\t\tconst onAbort = () => {\n\t\t\tif (!active) return;\n\t\t\tactive = false;\n\t\t\ta.down([[COMPLETE]]);\n\t\t};\n\t\tconst unsub = source.subscribe((msgs) => {\n\t\t\tif (!active) return;\n\t\t\tfor (const msg of msgs) {\n\t\t\t\tconst t = msg[0];\n\t\t\t\tif (defaultConfig.isLocalOnly(t)) {\n\t\t\t\t\tif (t === DIRTY && includeDirty) {\n\t\t\t\t\t\t/* fall through */\n\t\t\t\t\t} else continue;\n\t\t\t\t}\n\t\t\t\tif (t === DATA) {\n\t\t\t\t\temitFrame(dataEvent, serializeSseData(msg[1], serialize));\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (t === ERROR) {\n\t\t\t\t\temitFrame(errorEvent, serializeSseData(msg[1], serialize));\n\t\t\t\t\tactive = false;\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (t === COMPLETE) {\n\t\t\t\t\temitFrame(completeEvent);\n\t\t\t\t\tactive = false;\n\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!includeResolved && t === RESOLVED) continue;\n\t\t\t\temitFrame(\n\t\t\t\t\teventNameResolver(t),\n\t\t\t\t\tmsg.length > 1 ? serializeSseData(msg[1], serialize) : undefined,\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t\tif (keepAliveMs !== undefined && keepAliveMs > 0) {\n\t\t\tkeepAlive = setInterval(() => {\n\t\t\t\tif (!active) return;\n\t\t\t\ta.emit(encoder.encode(\": keepalive\\n\\n\"));\n\t\t\t}, keepAliveMs);\n\t\t}\n\t\tif (signal?.aborted) onAbort();\n\t\telse signal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\treturn () => {\n\t\t\tactive = false;\n\t\t\tif (keepAlive !== undefined) clearInterval(keepAlive);\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\tunsub();\n\t\t};\n\t});\n}\n\n/**\n * Converts a `Node<Uint8Array>` into a WHATWG `ReadableStream<Uint8Array>`.\n * Useful for composing with `new Response(...)` / `fetch` bodies.\n *\n * @category extra\n */\nexport function toReadableStream(bytes: Node<Uint8Array>): ReadableStream<Uint8Array> {\n\tlet unsub: (() => void) | undefined;\n\tlet closed = false;\n\treturn new ReadableStream<Uint8Array>({\n\t\tstart(controller) {\n\t\t\tunsub = bytes.subscribe((msgs) => {\n\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\tconst t = m[0];\n\t\t\t\t\tif (closed) return;\n\t\t\t\t\tif (t === DATA) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcontroller.enqueue(m[1] as Uint8Array);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t/* controller closed mid-batch — upstream unsub will follow */\n\t\t\t\t\t\t\tclosed = true;\n\t\t\t\t\t\t\tunsub?.();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (t === ERROR) {\n\t\t\t\t\t\tclosed = true;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcontroller.error(m[1]);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t/* controller already closed */\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (t === COMPLETE) {\n\t\t\t\t\t\tclosed = true;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t/* controller already closed */\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\tcancel() {\n\t\t\tclosed = true;\n\t\t\tunsub?.();\n\t\t},\n\t});\n}\n\n/** Parsed Server-Sent Event. */\nexport type SSEEvent<T = string> = {\n\tevent: string;\n\tdata: T;\n\tid?: string;\n\tretry?: number;\n};\n\n/** Options for {@link fromSSE}. */\nexport type FromSSEOptions<T = string> = ExtraOpts & {\n\t/** Parse the raw `data:` payload. Default: identity (string). */\n\tparse?: (raw: string) => T;\n};\n\n/** Options for {@link parseSSEStream}. */\nexport type ParseSSEStreamOptions<T = string> = {\n\t/** Parse the raw `data:` payload. Default: identity (string). */\n\tparse?: (raw: string) => T;\n\t/**\n\t * External abort signal. If aborted, the generator returns early after\n\t * cancelling the underlying reader / iterator. Does not emit an error —\n\t * the generator simply ends.\n\t */\n\tsignal?: AbortSignal;\n};\n\n/**\n * Parses a Server-Sent Events byte stream into an async-iterator of structured\n * `{event, data, id, retry}` records. Pure async generator with no reactive\n * dependency — safe to consume anywhere an `AsyncIterable<SSEEvent>` is\n * expected (LLM provider adapters, tests, non-reactive transports).\n *\n * Handles:\n * - Arbitrary chunk boundaries (internal text buffer + `TextDecoder` streaming).\n * - `\\n` and `\\r\\n` line endings.\n * - `event:` / `data:` (multi-line via repeated fields) / `id:` / `retry:`.\n * - Comments (`:` prefix).\n * - Cancels the underlying reader / iterator on external abort or consumer\n * break, so a quiet stream doesn't leak pending `read()` calls.\n *\n * Used internally by {@link fromSSE} (reactive `Node<SSEEvent>`) — exposed as a\n * pure helper so LLM provider adapters (Anthropic, OpenAI, Google) can parse\n * their SSE streams without building a reactive node per call.\n *\n * @param source - SSE byte source (`ReadableStream`, `Response`, or `AsyncIterable<Uint8Array>`).\n * @param opts - `{ parse?, signal? }`.\n * @returns `AsyncGenerator<SSEEvent<T>>` — yields one event per SSE block; returns on stream end / abort.\n *\n * @category extra\n */\nexport async function* parseSSEStream<T = string>(\n\tsource: ReadableStream<Uint8Array> | Response | AsyncIterable<Uint8Array>,\n\topts?: ParseSSEStreamOptions<T>,\n): AsyncGenerator<SSEEvent<T>, void, unknown> {\n\tconst parse = opts?.parse ?? ((raw: string) => raw as unknown as T);\n\tconst externalSignal = opts?.signal;\n\n\tconst decoder = new TextDecoder();\n\tlet buffer = \"\";\n\tlet currentEvent = \"message\";\n\tlet currentData: string[] = [];\n\tlet currentId: string | undefined;\n\tlet currentRetry: number | undefined;\n\tconst queue: SSEEvent<T>[] = [];\n\n\tconst flushEvent = () => {\n\t\tif (currentData.length === 0 && currentEvent === \"message\" && currentId === undefined) {\n\t\t\tcurrentData = [];\n\t\t\treturn;\n\t\t}\n\t\tconst raw = currentData.join(\"\\n\");\n\t\tqueue.push({\n\t\t\tevent: currentEvent,\n\t\t\tdata: parse(raw),\n\t\t\tid: currentId,\n\t\t\tretry: currentRetry,\n\t\t});\n\t\tcurrentEvent = \"message\";\n\t\tcurrentData = [];\n\t\tcurrentId = undefined;\n\t\tcurrentRetry = undefined;\n\t};\n\n\tconst processLine = (line: string) => {\n\t\tif (line === \"\") {\n\t\t\tflushEvent();\n\t\t\treturn;\n\t\t}\n\t\tif (line.startsWith(\":\")) return; // comment\n\t\tconst colon = line.indexOf(\":\");\n\t\tconst field = colon < 0 ? line : line.slice(0, colon);\n\t\tlet value = colon < 0 ? \"\" : line.slice(colon + 1);\n\t\tif (value.startsWith(\" \")) value = value.slice(1);\n\t\tswitch (field) {\n\t\t\tcase \"event\":\n\t\t\t\tcurrentEvent = value;\n\t\t\t\tbreak;\n\t\t\tcase \"data\":\n\t\t\t\tcurrentData.push(value);\n\t\t\t\tbreak;\n\t\t\tcase \"id\":\n\t\t\t\tif (!value.includes(\"\\0\")) currentId = value;\n\t\t\t\tbreak;\n\t\t\tcase \"retry\": {\n\t\t\t\tconst n = Number(value);\n\t\t\t\tif (Number.isFinite(n)) currentRetry = n;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t};\n\n\tconst processChunk = (chunk: Uint8Array, done: boolean) => {\n\t\tbuffer += decoder.decode(chunk, { stream: !done });\n\t\tconst parts = buffer.split(/\\r?\\n/);\n\t\tbuffer = parts.pop() ?? \"\";\n\t\tfor (const line of parts) processLine(line);\n\t};\n\n\t// Resolve the underlying byte source into either a `ReadableStream` or an\n\t// `AsyncIterator<Uint8Array>` — identical dispatch as the legacy fromSSE.\n\tconst resp = source as Response;\n\tconst stream =\n\t\tsource instanceof ReadableStream\n\t\t\t? source\n\t\t\t: resp && typeof resp === \"object\" && resp.body instanceof ReadableStream\n\t\t\t\t? resp.body\n\t\t\t\t: null;\n\n\tlet reader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n\tlet iter: AsyncIterator<Uint8Array> | undefined;\n\t// `cleanupDone` flips once we've invoked `reader.cancel()` / `iter.return()`\n\t// — guards against the `onAbort` listener + the `finally` path both\n\t// cancelling the same underlying resource (WHATWG streams allow double-\n\t// cancel but custom `AsyncIterator.return` implementations are not\n\t// required to be idempotent).\n\tlet cleanupDone = false;\n\tconst cleanupReader = (): void => {\n\t\tif (cleanupDone) return;\n\t\tcleanupDone = true;\n\t\tif (reader) {\n\t\t\tvoid reader.cancel().catch(() => undefined);\n\t\t}\n\t\tif (iter && typeof iter.return === \"function\") {\n\t\t\tvoid Promise.resolve(iter.return()).catch(() => undefined);\n\t\t}\n\t};\n\n\t// Wire the external abort signal to cancel the reader / iterator promptly\n\t// instead of waiting for the next chunk.\n\tconst onAbort = (): void => {\n\t\tcleanupReader();\n\t};\n\tif (externalSignal) {\n\t\tif (externalSignal.aborted) return;\n\t\texternalSignal.addEventListener(\"abort\", onAbort, { once: true });\n\t}\n\n\ttry {\n\t\tif (stream) {\n\t\t\treader = stream.getReader();\n\t\t\twhile (!externalSignal?.aborted) {\n\t\t\t\tconst { value, done } = await reader.read();\n\t\t\t\tif (done) break;\n\t\t\t\tprocessChunk(value, false);\n\t\t\t\twhile (queue.length > 0) {\n\t\t\t\t\tconst ev = queue.shift() as SSEEvent<T>;\n\t\t\t\t\tyield ev;\n\t\t\t\t}\n\t\t\t}\n\t\t\tprocessChunk(new Uint8Array(), true);\n\t\t} else {\n\t\t\tconst asyncIter = source as AsyncIterable<Uint8Array>;\n\t\t\titer = asyncIter[Symbol.asyncIterator]();\n\t\t\twhile (!externalSignal?.aborted) {\n\t\t\t\tconst step = await iter.next();\n\t\t\t\tif (step.done) break;\n\t\t\t\tprocessChunk(step.value, false);\n\t\t\t\twhile (queue.length > 0) {\n\t\t\t\t\tconst ev = queue.shift() as SSEEvent<T>;\n\t\t\t\t\tyield ev;\n\t\t\t\t}\n\t\t\t}\n\t\t\tprocessChunk(new Uint8Array(), true);\n\t\t}\n\t\tif (buffer.trim()) {\n\t\t\tfor (const line of buffer.split(/\\r?\\n/)) processLine(line);\n\t\t\tflushEvent();\n\t\t}\n\t\twhile (queue.length > 0) {\n\t\t\tconst ev = queue.shift() as SSEEvent<T>;\n\t\t\tyield ev;\n\t\t}\n\t} finally {\n\t\tif (externalSignal) {\n\t\t\texternalSignal.removeEventListener(\"abort\", onAbort);\n\t\t}\n\t\t// Idempotent cleanup — if `onAbort` already ran the cancel, this is a\n\t\t// no-op. Covers the normal consumer-break path (generator exits → finally\n\t\t// runs → cancel underlying reader / iterator so a quiet upstream\n\t\t// doesn't leak its `read()` call).\n\t\tcleanupReader();\n\t}\n}\n\n/**\n * Parses a Server-Sent Events stream into structured `{event, data, id}` records.\n *\n * @param source - SSE byte source (`ReadableStream`, `Response`, or `AsyncIterable<Uint8Array>`).\n * @param opts - Parse function and node options.\n * @returns `Node<SSEEvent<T>>` — one `DATA` per SSE event; `COMPLETE` on stream end.\n *\n * @category extra\n */\nexport function fromSSE<T = string>(\n\tsource: ReadableStream<Uint8Array> | Response | AsyncIterable<Uint8Array>,\n\topts?: FromSSEOptions<T>,\n): Node<SSEEvent<T>> {\n\tconst { parse, ...rest } = opts ?? {};\n\treturn node<SSEEvent<T>>(\n\t\t[],\n\t\t(_data, a) => {\n\t\t\tlet active = true;\n\t\t\tconst ctrl = new AbortController();\n\t\t\tconst run = async () => {\n\t\t\t\ttry {\n\t\t\t\t\tfor await (const ev of parseSSEStream<T>(source, { parse, signal: ctrl.signal })) {\n\t\t\t\t\t\tif (!active) return;\n\t\t\t\t\t\ta.emit(ev);\n\t\t\t\t\t}\n\t\t\t\t\tif (active) a.down([[COMPLETE]]);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (active) a.down([[ERROR, err]]);\n\t\t\t\t}\n\t\t\t};\n\t\t\tvoid run();\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t\tctrl.abort();\n\t\t\t};\n\t\t},\n\t\tsourceOpts(rest),\n\t);\n}\n","/**\n * DryRunAdapter — zero-cost mock provider.\n *\n * Returns a deterministic fake response (plus a configurable hook for\n * customization). Useful for: pipeline smoke tests, CI without API keys,\n * local development, and as the leaf of a `cascadingLlmAdapter` when every\n * real tier fails.\n *\n * The library ships a minimal implementation only — richer scenario-\n * scripted mocks (per-stage responses, call recording) belong at the test\n * harness layer, not in the shipped library.\n *\n * Uses `ResettableTimer` for simulated latency (spec §5.10 escape hatch\n * documented on the class), and throws an `AbortError`-named Error on\n * abort so retry/timeout middleware can classify it.\n */\n\nimport { ResettableTimer } from \"@graphrefly/pure-ts/core\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n\tTokenUsage,\n} from \"../core/types.js\";\n\nexport interface DryRunAdapterOptions {\n\tprovider?: string;\n\tmodel?: string;\n\t/** Generate the fake response. Defaults to echoing the last user message. */\n\trespond?: (messages: readonly ChatMessage[], opts?: LLMInvokeOptions) => string;\n\t/**\n\t * Generate a fake usage object. Defaults to a simple character-count\n\t * heuristic (`input = sum(messages) / 4`, `output = content / 4`).\n\t */\n\tusage?: (messages: readonly ChatMessage[], content: string) => TokenUsage;\n\t/** Simulated latency in milliseconds (applied to both invoke and stream). */\n\tlatencyMs?: number;\n\t/** Stream chunk size in characters. Default 16. */\n\tstreamChunkSize?: number;\n}\n\nfunction makeAbortError(): Error {\n\tconst err = new Error(\"aborted\") as Error & { name: string };\n\terr.name = \"AbortError\";\n\treturn err;\n}\n\n/**\n * Abort-aware sleep using `ResettableTimer`. Spec §5.10 escape hatch.\n * No-op if `ms <= 0`; rejects with `AbortError` if the signal aborts.\n */\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\tif (ms <= 0) return Promise.resolve();\n\tif (signal?.aborted) return Promise.reject(makeAbortError());\n\treturn new Promise((resolve, reject) => {\n\t\tconst timer = new ResettableTimer();\n\t\tlet onAbort: (() => void) | undefined;\n\t\tconst cleanup = (): void => {\n\t\t\ttimer.cancel();\n\t\t\tif (signal && onAbort) signal.removeEventListener(\"abort\", onAbort);\n\t\t};\n\t\ttimer.start(ms, () => {\n\t\t\tcleanup();\n\t\t\tresolve();\n\t\t});\n\t\tif (signal) {\n\t\t\tonAbort = (): void => {\n\t\t\t\tcleanup();\n\t\t\t\treject(makeAbortError());\n\t\t\t};\n\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t}\n\t});\n}\n\n/**\n * Create a DryRun adapter.\n *\n * @example\n * ```ts\n * const adapter = dryRunAdapter({ respond: (msgs) => \"hello from dry-run\" });\n * const resp = await Promise.resolve(adapter.invoke([{ role: \"user\", content: \"hi\" }]));\n * ```\n */\nexport function dryRunAdapter(opts: DryRunAdapterOptions = {}): LLMAdapter {\n\tconst provider = opts.provider ?? \"dry-run\";\n\tconst model = opts.model ?? \"dry-run-v1\";\n\tconst latencyMs = opts.latencyMs ?? 0;\n\tconst streamChunkSize = Math.max(1, opts.streamChunkSize ?? 16);\n\n\tconst respondFn =\n\t\topts.respond ??\n\t\t((msgs: readonly ChatMessage[]): string => {\n\t\t\tconst lastUser = [...msgs].reverse().find((m) => m.role === \"user\");\n\t\t\treturn lastUser ? `echo: ${lastUser.content}` : \"dry-run: no user message\";\n\t\t});\n\n\tconst usageFn =\n\t\topts.usage ??\n\t\t((msgs: readonly ChatMessage[], content: string): TokenUsage => {\n\t\t\tconst totalInput = msgs.reduce((s, m) => s + m.content.length, 0);\n\t\t\treturn {\n\t\t\t\tinput: { regular: Math.ceil(totalInput / 4) },\n\t\t\t\toutput: { regular: Math.ceil(content.length / 4) },\n\t\t\t};\n\t\t});\n\n\treturn {\n\t\tprovider,\n\t\tmodel,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tawait sleep(latencyMs, invokeOpts?.signal);\n\t\t\tif (invokeOpts?.signal?.aborted) throw makeAbortError();\n\t\t\tconst content = respondFn(messages, invokeOpts);\n\t\t\tconst usage = usageFn(messages, content);\n\t\t\treturn {\n\t\t\t\tcontent,\n\t\t\t\tusage,\n\t\t\t\tfinishReason: \"stop\",\n\t\t\t\tmodel: invokeOpts?.model ?? model,\n\t\t\t\tprovider,\n\t\t\t\ttier: invokeOpts?.tier,\n\t\t\t\tmetadata: { dryRun: true },\n\t\t\t};\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst content = respondFn(messages, invokeOpts);\n\t\t\tconst usage = usageFn(messages, content);\n\t\t\tconst chunkCount = Math.ceil(content.length / streamChunkSize) || 1;\n\t\t\tconst perChunkMs = latencyMs > 0 ? latencyMs / chunkCount : 0;\n\t\t\tfor (let i = 0; i < content.length; i += streamChunkSize) {\n\t\t\t\tif (invokeOpts?.signal?.aborted) throw makeAbortError();\n\t\t\t\tawait sleep(perChunkMs, invokeOpts?.signal);\n\t\t\t\tyield { type: \"token\", delta: content.slice(i, i + streamChunkSize) };\n\t\t\t}\n\t\t\tyield { type: \"usage\", usage };\n\t\t\tyield { type: \"finish\", reason: \"stop\" };\n\t\t},\n\t};\n}\n","/**\n * `fallbackAdapter` — fixture-backed {@link LLMAdapter} for offline demos,\n * deterministic tests, and graceful degradation in production.\n *\n * A peer of `anthropicAdapter` / `openAICompatAdapter` / `googleAdapter` /\n * `ollamaAdapter` / `dryRunAdapter`, but whose role is to serve pre-recorded\n * or canned responses when real providers aren't reachable. Install it as a\n * tier via the existing routing primitives (no new composer needed):\n *\n * ```ts\n * // Graceful offline fallback for a user app:\n * resilientAdapter(anthropicAdapter({ ... }), {\n * fallback: fallbackAdapter({ fixturesDir: \"./fixtures\" }),\n * });\n *\n * // Or the general N-tier shape:\n * cascadingLlmAdapter([\n * { name: \"primary\", adapter: anthropicAdapter({ ... }) },\n * { name: \"fallback\", adapter: fallbackAdapter({ fixturesDir: \"./fixtures\" }) },\n * ]);\n * ```\n *\n * The `provider` field is `\"fallback\"` so its role is self-documenting in\n * logs, stats, cost tables, and audit trails.\n *\n * ## Three fixture sources (mutually exclusive)\n *\n * Pick exactly one of:\n *\n * 1. **`fixtures: FallbackFixture[]`** — inline, hand-authored. Supports\n * both hash-keyed and messages-keyed shapes; the adapter computes the\n * canonical hash for messages-keyed entries at init time. Ideal when you\n * want full control in code (tests, small demos).\n *\n * 2. **`fixturesStorage: KvStorageTier`** — the escape hatch for any backend.\n * Pass a `memoryKv()`, `indexedDbKv(...)`, `sqliteKv(...)`,\n * `cascadingCache(...)`, or a custom tier. You own the layout — no\n * auto-namespacing.\n *\n * **Filesystem directories (Node only):** the core `fallbackAdapter`\n * does NOT import `node:fs` / `node:path` — it's safe to bundle for\n * browsers. For a directory convenience, import `fallbackAdapter` from\n * `@graphrefly/graphrefly/patterns/ai/node` (node subpath);\n * that variant adds `fixturesDir: string` (auto-namespaced to\n * `join(dir, keyPrefix)`, cache-format validated at init).\n *\n * ## Record mode\n *\n * `record: { adapter: real, storage }` proxies every call to `real` AND\n * persists the response through the provided tier. Use the node subpath's\n * `fallbackAdapter` for `record.dir` (auto-namespaced + `record.dir` defaults\n * to `fixturesDir` when both are file-backed).\n *\n * ## Three use cases, one implementation\n *\n * | Use case | Config |\n * |---|---|\n * | **User apps** — degrade when the cloud provider errors or network is down | `fallbackAdapter({ fixturesStorage: ... })` installed as a fallback tier |\n * | **Tests** — deterministic replays, fail loudly on miss | `fallbackAdapter({ fixturesStorage: ..., onMiss: \"throw\" })` |\n * | **Eval offline replay** — zero-spend repeat runs | `fallbackAdapter({ fixturesStorage: ... })` as the only adapter |\n *\n * ## Implementation\n *\n * Thin sugar over {@link withReplayCache}. Key shape comes from its\n * `canonicalJson` — fixtures written by either tool are interchangeable.\n *\n * @module\n */\n\nimport { sha256Hex, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { canonicalJson, type KvStorageTier, memoryKv } from \"@graphrefly/pure-ts/extra\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n} from \"../core/types.js\";\nimport {\n\ttype ReplayCacheKeyContext,\n\tReplayCacheMissError,\n\twithReplayCache,\n} from \"../middleware/replay-cache.js\";\nimport { dryRunAdapter } from \"./dry-run.js\";\n\nexport type FallbackMissPolicy = \"throw\" | \"respond\";\n\n/**\n * Thrown when `fallbackAdapter({ onMiss: \"throw\" })` receives a request that\n * has no matching fixture. Alias of `ReplayCacheMissError` for now — the\n * adapter is a thin sugar over `withReplayCache` and shares its miss-error.\n */\nexport const FallbackMissError = ReplayCacheMissError;\nexport type FallbackMissError = ReplayCacheMissError;\n\n/**\n * One recorded fixture. Two authoring shapes:\n * - **Hash-keyed** — `{ key, response, stream? }`. Key is `sha256(canonicalJson({messages, opts}))`\n * with `fallback:` prefix. This is what `record` mode writes.\n * - **Messages-keyed** — `{ messages, invokeOpts?, response }`. The adapter\n * computes the key at init time. Ergonomic for hand-authored fixtures.\n */\nexport type FallbackFixture =\n\t| {\n\t\t\treadonly key: string;\n\t\t\treadonly response: LLMResponse;\n\t\t\treadonly stream?: {\n\t\t\t\treadonly chunks: readonly StreamDelta[];\n\t\t\t\treadonly delaysMs?: readonly number[];\n\t\t\t};\n\t }\n\t| {\n\t\t\treadonly messages: readonly ChatMessage[];\n\t\t\treadonly invokeOpts?: Omit<LLMInvokeOptions, \"signal\">;\n\t\t\treadonly response: LLMResponse;\n\t };\n\nexport interface FallbackAdapterOptions {\n\t/** Adapter provider label. Default `\"fallback\"`. */\n\treadonly provider?: string;\n\t/** Adapter model label. Default `\"fallback\"`. */\n\treadonly model?: string;\n\t/**\n\t * Inline hand-authored fixtures. Supports both hash-keyed (`{key, response, stream?}`)\n\t * and messages-keyed (`{messages, invokeOpts?, response}`) shapes — the adapter\n\t * computes the canonical hash for messages-keyed entries at init time. Held in\n\t * an internal `memoryKv`. Mutually exclusive with `fixturesDir` and\n\t * `fixturesStorage`.\n\t */\n\treadonly fixtures?: readonly FallbackFixture[];\n\t/**\n\t * Bring-your-own `KvStorageTier` (`memoryKv`, `sqliteKv`,\n\t * `indexedDbKv`, `cascadingCache`, or a custom tier). You own the\n\t * layout — no auto-namespacing. Mutually exclusive with `fixtures`.\n\t *\n\t * For filesystem directories, use the node subpath's `fallbackAdapter`\n\t * with its `fixturesDir` option (auto-namespaced + validated).\n\t */\n\treadonly fixturesStorage?: KvStorageTier;\n\t/**\n\t * Called on fixture miss when `onMiss === \"respond\"`. If not provided and\n\t * `onMiss === \"respond\"`, a canned \"service unavailable\" response is\n\t * returned (marked with `metadata.degraded: true`).\n\t */\n\treadonly respond?: (\n\t\tmessages: readonly ChatMessage[],\n\t\topts?: LLMInvokeOptions,\n\t) => string | LLMResponse;\n\t/** Miss policy. Default `\"respond\"`. */\n\treadonly onMiss?: FallbackMissPolicy;\n\t/**\n\t * Record mode. Proxies every call to `record.adapter` AND persists the\n\t * result through `record.storage`. For filesystem `record.dir` convenience,\n\t * use the node subpath's `fallbackAdapter`.\n\t */\n\treadonly record?: {\n\t\treadonly adapter: LLMAdapter;\n\t\treadonly storage?: KvStorageTier;\n\t};\n\t/** Stream replay speed multiplier. See {@link withReplayCache}. Default `1`. */\n\treadonly replaySpeed?: number;\n\t/** Key prefix. Kept compatible with `withReplayCache` defaults. Default `\"fallback\"`. */\n\treadonly keyPrefix?: string;\n\t/**\n\t * Custom key function — forwarded directly to the underlying\n\t * {@link withReplayCache}. Use to shard fixtures by `invokeOpts.keyContext`\n\t * (tenant, session, feature flag). Accepts either the new\n\t * {@link ReplayCacheKeyContext} object form or the legacy 2-arg\n\t * `(messages, opts?)` form.\n\t */\n\treadonly keyFn?:\n\t\t| ((ctx: ReplayCacheKeyContext) => string)\n\t\t| ((messages: readonly ChatMessage[], opts?: LLMInvokeOptions) => string);\n}\n\n// ---------------------------------------------------------------------------\n// Canned degraded response\n// ---------------------------------------------------------------------------\n\nfunction degradedResponse(provider: string, model: string): LLMResponse {\n\treturn {\n\t\tcontent: \"[fallback: no cached response available for this request]\",\n\t\tusage: { input: { regular: 0 }, output: { regular: 0 } },\n\t\tfinishReason: \"stop\",\n\t\tmodel,\n\t\tprovider,\n\t\tmetadata: { degraded: true, reason: \"no-fixture\" },\n\t};\n}\n\nfunction normalizeRespondResult(\n\traw: string | LLMResponse,\n\tprovider: string,\n\tmodel: string,\n): LLMResponse {\n\tif (typeof raw === \"string\") {\n\t\treturn {\n\t\t\tcontent: raw,\n\t\t\tusage: { input: { regular: 0 }, output: { regular: 0 } },\n\t\t\tfinishReason: \"stop\",\n\t\t\tmodel,\n\t\t\tprovider,\n\t\t\tmetadata: { degraded: true, reason: \"respond\" },\n\t\t};\n\t}\n\treturn raw;\n}\n\n// ---------------------------------------------------------------------------\n// Fixture → storage tier conversion\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the key a `FallbackFixture` would hash to. Messages-keyed fixtures\n * get their key derived on the spot; hash-keyed fixtures pass through. Async\n * because `sha256Hex` uses `globalThis.crypto.subtle` (universal, no\n * `node:crypto` leak) — see {@link sha256Hex}.\n */\nasync function fixtureKey(fixture: FallbackFixture, keyPrefix: string): Promise<string> {\n\tif (\"key\" in fixture) return fixture.key;\n\tconst canonical = canonicalJson({ messages: fixture.messages, opts: fixture.invokeOpts ?? {} });\n\tconst hex = await sha256Hex(canonical);\n\treturn `${keyPrefix}:${hex}`;\n}\n\n/**\n * `withReplayCache` stores values as `CachedEntry = { response, storedAtNs, streamChunks?, streamCadenceMs? }`.\n * Convert a `FallbackFixture` into that shape so inline fixtures can be\n * seeded into a memory tier alongside file-authored ones.\n */\nfunction toCachedEntry(fixture: FallbackFixture): unknown {\n\tconst base: { response: LLMResponse; storedAtNs: number } = {\n\t\tresponse: fixture.response,\n\t\t// Real timestamp so future TTL-aware tiers don't treat inline fixtures\n\t\t// as Epoch-old and evict them on first pass. Matches the wall-clock\n\t\t// write `withReplayCache` uses for disk-written entries.\n\t\tstoredAtNs: wallClockNs(),\n\t};\n\tif (\"key\" in fixture && fixture.stream) {\n\t\tconst tokenChunks = fixture.stream.chunks.filter(\n\t\t\t(c): c is Extract<StreamDelta, { type: \"token\" }> => c.type === \"token\",\n\t\t);\n\t\treturn {\n\t\t\t...base,\n\t\t\tstreamChunks: tokenChunks.map((c) => ({ delta: c.delta })),\n\t\t\tstreamCadenceMs: fixture.stream.delaysMs ?? tokenChunks.map(() => 0),\n\t\t};\n\t}\n\treturn base;\n}\n\n/**\n * Resolve the fixture source to a `KvStorageTier`. Enforces mutual exclusion\n * between `fixtures` and `fixturesStorage`. When `fixtures` is provided, the\n * seeded memory tier is returned synchronously but keys are populated\n * asynchronously via the returned seeding promise (await before first use).\n */\nfunction resolveFixtureStorage(\n\topts: FallbackAdapterOptions,\n\tkeyPrefix: string,\n): { tier: KvStorageTier | undefined; seedReady: Promise<void> } {\n\tconst sources: string[] = [];\n\tif (opts.fixtures != null) sources.push(\"fixtures\");\n\tif (opts.fixturesStorage != null) sources.push(\"fixturesStorage\");\n\tif (sources.length > 1) {\n\t\tthrow new TypeError(\n\t\t\t`fallbackAdapter: \\`fixtures\\` and \\`fixturesStorage\\` are mutually ` +\n\t\t\t\t`exclusive; got both ${sources.join(\" and \")}. Pick one source. ` +\n\t\t\t\t`For filesystem directories use the node subpath's \\`fallbackAdapter\\`.`,\n\t\t);\n\t}\n\tif (opts.fixtures) {\n\t\tconst tier = memoryKv();\n\t\tconst fixtures = opts.fixtures;\n\t\tconst seedReady = (async () => {\n\t\t\tfor (const fixture of fixtures) {\n\t\t\t\tconst key = await fixtureKey(fixture, keyPrefix);\n\t\t\t\tawait tier.save(key, toCachedEntry(fixture));\n\t\t\t}\n\t\t})();\n\t\t// Attach a no-op catch so a failure inside the IIFE (e.g. `sha256Hex`\n\t\t// throws because `globalThis.crypto.subtle` is unavailable) does NOT\n\t\t// become an unhandled rejection when the adapter is constructed but\n\t\t// never invoked. V8 records the handler attachment via this branch\n\t\t// of the promise graph, so the Node `unhandledRejection` hook stays\n\t\t// silent — yet subsequent `await seedReady` inside `invoke`/`stream`\n\t\t// still throws the original error for the caller to see.\n\t\tseedReady.catch(() => {});\n\t\treturn { tier, seedReady };\n\t}\n\tif (opts.fixturesStorage) return { tier: opts.fixturesStorage, seedReady: Promise.resolve() };\n\treturn { tier: undefined, seedReady: Promise.resolve() };\n}\n\n// ---------------------------------------------------------------------------\n// fallbackAdapter\n// ---------------------------------------------------------------------------\n\n/**\n * Build a fixture-backed {@link LLMAdapter}. See module docs for use cases\n * (offline demo, tests, degraded-mode) and recipe snippets.\n */\nexport function fallbackAdapter(opts: FallbackAdapterOptions = {}): LLMAdapter {\n\tconst provider = opts.provider ?? \"fallback\";\n\tconst model = opts.model ?? \"fallback\";\n\tconst onMiss: FallbackMissPolicy = opts.onMiss ?? \"respond\";\n\tconst keyPrefix = opts.keyPrefix ?? \"fallback\";\n\n\t// Pick the inner leaf adapter based on mode.\n\tconst leaf: LLMAdapter = (() => {\n\t\tif (opts.record) return opts.record.adapter;\n\t\tif (onMiss === \"throw\") {\n\t\t\t// `withReplayCache({ mode: \"read-strict\" })` throws on miss before\n\t\t\t// ever calling the inner. Supply a no-op to satisfy the type.\n\t\t\treturn dryRunAdapter({\n\t\t\t\tprovider,\n\t\t\t\tmodel,\n\t\t\t\trespond: () => \"[unreachable: read-strict mode throws on miss]\",\n\t\t\t});\n\t\t}\n\t\t// Custom leaf (not `dryRunAdapter`) so `metadata.degraded` is preserved\n\t\t// — `dryRunAdapter` returns a string and constructs its own response,\n\t\t// discarding our metadata. For the respond-on-miss path we want full\n\t\t// `LLMResponse` control.\n\t\treturn {\n\t\t\tprovider,\n\t\t\tmodel,\n\t\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\t\tconst raw = opts.respond\n\t\t\t\t\t? opts.respond(messages, invokeOpts)\n\t\t\t\t\t: degradedResponse(provider, model);\n\t\t\t\treturn normalizeRespondResult(raw, provider, model);\n\t\t\t},\n\t\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\t\tconst raw = opts.respond\n\t\t\t\t\t? opts.respond(messages, invokeOpts)\n\t\t\t\t\t: degradedResponse(provider, model);\n\t\t\t\tconst r = normalizeRespondResult(raw, provider, model);\n\t\t\t\tyield { type: \"token\", delta: r.content };\n\t\t\t\tif (r.usage) yield { type: \"usage\", usage: r.usage };\n\t\t\t\tyield { type: \"finish\", reason: r.finishReason ?? \"stop\" };\n\t\t\t},\n\t\t} satisfies LLMAdapter;\n\t})();\n\n\t// Resolve the storage tier.\n\t// - `record` mode: require `record.storage`.\n\t// - Replay-only: `fixtures` seeds an in-memory tier (async) OR\n\t// `fixturesStorage` passes through.\n\tlet storage: KvStorageTier;\n\tlet seedReady: Promise<void> = Promise.resolve();\n\tif (opts.record) {\n\t\tif (!opts.record.storage) {\n\t\t\tthrow new TypeError(\n\t\t\t\t\"fallbackAdapter: `record.storage` is required in record mode. For filesystem \" +\n\t\t\t\t\t\"`record.dir` convenience, use the node subpath's `fallbackAdapter`.\",\n\t\t\t);\n\t\t}\n\t\tstorage = opts.record.storage;\n\t} else {\n\t\tconst resolved = resolveFixtureStorage(opts, keyPrefix);\n\t\tstorage = resolved.tier ?? memoryKv();\n\t\tseedReady = resolved.seedReady;\n\t}\n\n\tconst mode = opts.record ? \"read-write\" : onMiss === \"throw\" ? \"read-strict\" : \"read\";\n\n\tconst cached = withReplayCache(leaf, {\n\t\tstorage,\n\t\tmode,\n\t\tkeyPrefix,\n\t\tcacheStreaming: true,\n\t\tcaptureStreamCadence: true,\n\t\treplaySpeed: opts.replaySpeed,\n\t\t...(opts.keyFn ? { keyFn: opts.keyFn } : {}),\n\t});\n\n\t// Wrap invoke/stream so the first call awaits the seed-complete Promise.\n\t// Adapter construction stays synchronous (`fallbackAdapter(...)` returns\n\t// immediately); inline fixture hashing happens lazily on first use.\n\treturn {\n\t\tprovider,\n\t\tmodel,\n\t\tcapabilities: cached.capabilities?.bind(cached),\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tawait seedReady;\n\t\t\t// `cached` came from `withReplayCache`, whose `invoke` always returns\n\t\t\t// `Promise<LLMResponse>`. The `LLMAdapter` interface types it as the\n\t\t\t// broader `NodeInput<LLMResponse>` union; narrow here to the actual\n\t\t\t// shape so the wrapper surface stays `Promise<LLMResponse>`.\n\t\t\treturn cached.invoke(messages, invokeOpts) as Promise<LLMResponse>;\n\t\t},\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tawait seedReady;\n\t\t\tfor await (const delta of cached.stream(messages, invokeOpts)) yield delta;\n\t\t},\n\t};\n}\n","/**\n * `withReplayCache` — content-addressed response cache over `KvStorageTier`.\n *\n * - Key: sha256 of canonicalized (messages + invoke options minus `signal`).\n * - `\"read-write\"` (default): returns cached response if present; on miss,\n * passes through and stores the result.\n * - `\"write-only\"`: never reads; populates the cache for later runs.\n * - `\"read\"`: reads only; on miss, passes through without writing.\n * - `\"read-strict\"`: reads only; on miss, **throws `ReplayCacheMissError`**\n * instead of passing through. Use for fixture-driven tests or offline\n * fallback adapters where any cache miss is a test failure or a signal to\n * degrade.\n *\n * Reuses the library's existing `KvStorageTier` abstraction — any kv tier\n * (memoryKv / fileKv / sqliteKv / indexedDbKv / custom).\n *\n * **Concurrent cache-miss dedup:** uses `singleFromAny` so two concurrent\n * calls with the same key share one upstream request. Second caller sees the\n * same response that the first caller fetched; no duplicate provider spend.\n *\n * **Circular-ref safe:** `canonicalJson` uses a seen-set replacer so\n * user-supplied `ToolDefinition.parameters` with `$ref` cycles don't stack-\n * overflow the key computation.\n *\n * **Stream cadence capture:** when `cacheStreaming: true` AND\n * `captureStreamCadence: true`, per-chunk delays (ms since previous chunk)\n * are recorded alongside the content. Replay honors the recorded cadence\n * unless `replaySpeed` is set, which multiplies the effective per-chunk\n * delay (`replaySpeed: 2` → 2× faster; `replaySpeed: 0` → instant).\n * Without `captureStreamCadence`, replay is instant regardless.\n */\n\nimport { monotonicNs, ResettableTimer, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport type { KvStorageTier } from \"@graphrefly/pure-ts/extra\";\nimport { fromAny } from \"@graphrefly/pure-ts/extra\";\nimport { singleFromAny } from \"../../../../base/composition/single-from-any.js\";\nimport { firstValueFrom } from \"../../../../base/sources/settled.js\";\nimport { contentAddressedCache } from \"../_internal/content-addressed-cache.js\";\nimport { adapterWrapper, withLayer } from \"../_internal/wrappers.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n} from \"../core/types.js\";\n\nexport type ReplayCacheMode = \"read\" | \"read-strict\" | \"write-only\" | \"read-write\";\n\nexport class ReplayCacheMissError extends Error {\n\toverride name = \"ReplayCacheMissError\";\n\tconstructor(\n\t\tpublic readonly key: string,\n\t\tpublic readonly method: \"invoke\" | \"stream\",\n\t) {\n\t\tsuper(`withReplayCache: no cached response for ${method} (key=${key}, mode=read-strict)`);\n\t}\n}\n\n/**\n * Context object passed to {@link WithReplayCacheOptions.keyFn}. Extending\n * with additional fields is forward-compatible — current implementations\n * ignoring unknown fields continue to work.\n */\nexport interface ReplayCacheKeyContext {\n\treadonly messages: readonly ChatMessage[];\n\treadonly opts: LLMInvokeOptions | undefined;\n\t/** Shortcut to `opts?.keyContext` — avoids an extra guard in callers. */\n\treadonly context: unknown;\n}\n\nexport interface WithReplayCacheOptions {\n\tstorage: KvStorageTier;\n\tmode?: ReplayCacheMode;\n\t/**\n\t * Custom key function. Receives a {@link ReplayCacheKeyContext} with the\n\t * chat messages, the invoke options, and the caller-supplied\n\t * `opts.keyContext`. Defaults to sha256 of canonical JSON over\n\t * `(messages, opts without signal/keyContext)`.\n\t *\n\t * Legacy 2-arg form `(messages, opts?)` also accepted — the adapter\n\t * detects arity and dispatches. Prefer the object form for new code.\n\t */\n\tkeyFn?:\n\t\t| ((ctx: ReplayCacheKeyContext) => string | Promise<string>)\n\t\t| ((messages: readonly ChatMessage[], opts?: LLMInvokeOptions) => string | Promise<string>);\n\t/** Prefix for cached keys (useful when sharing a tier across domains). */\n\tkeyPrefix?: string;\n\t/**\n\t * Whether to cache streaming responses (by consuming the full stream\n\t * and replaying it as one synthetic token chunk). Default `false`.\n\t */\n\tcacheStreaming?: boolean;\n\t/**\n\t * When `cacheStreaming: true`, also record per-chunk delays (ms since\n\t * previous chunk) so replay can honor the original streaming cadence.\n\t * Default `false` (chunks replay instantly).\n\t */\n\tcaptureStreamCadence?: boolean;\n\t/**\n\t * Stream replay speed multiplier. `1` = original cadence (requires\n\t * `captureStreamCadence`). `2` = 2× faster. `0` = instant. Default `1`.\n\t */\n\treplaySpeed?: number;\n}\n\ninterface CachedEntry {\n\tresponse: LLMResponse;\n\tstoredAtNs: number;\n\t/**\n\t * Per-chunk deltas in milliseconds — populated only when `captureStreamCadence`\n\t * is `true` during the write. Replayed via `ResettableTimer` in stream().\n\t */\n\tstreamCadenceMs?: readonly number[];\n\t/**\n\t * Per-chunk bodies in order (tokens only — `usage`/`finish` are reconstructed\n\t * from `response.usage` / `response.finishReason`). Populated only when\n\t * `captureStreamCadence` is `true`, used for cadence-faithful replay.\n\t */\n\tstreamChunks?: ReadonlyArray<{ delta: string }>;\n}\n\ntype ResolveArgs = {\n\tmessages: readonly ChatMessage[];\n\tinvokeOpts: LLMInvokeOptions | undefined;\n};\ntype ResolveArgsWithKey = ResolveArgs & { _precomputedKey: string };\n\n/** Wrap an adapter with a replay cache. */\nexport function withReplayCache(inner: LLMAdapter, opts: WithReplayCacheOptions): LLMAdapter {\n\tconst mode = opts.mode ?? \"read-write\";\n\tconst cacheStreaming = opts.cacheStreaming ?? false;\n\tconst captureStreamCadence = opts.captureStreamCadence ?? false;\n\tconst replaySpeed = opts.replaySpeed ?? 1;\n\tconst keyPrefix = opts.keyPrefix ?? \"llm-replay\";\n\tconst isReadOnly = mode === \"read\" || mode === \"read-strict\";\n\n\t// Content-addressed substrate — keys via canonicalJson + sha256 over\n\t// (messages, opts minus signal/keyContext) or the caller's custom keyFn.\n\t// Value type is `CachedEntry` so we can persist stream cadence alongside\n\t// the response. Uses the shared substrate in `src/extra/content-addressed-\n\t// storage.ts` via the LLM-specific wrapper in `_internal/`.\n\t//\n\t// Mode translation: `ReplayCacheMode` uses `\"write-only\"` (legacy name);\n\t// the substrate uses `\"write\"`. All other modes map 1:1.\n\tconst cache = contentAddressedCache<CachedEntry>({\n\t\tstorage: opts.storage,\n\t\tmode: mode === \"write-only\" ? \"write\" : mode,\n\t\tkeyFn: opts.keyFn,\n\t\tkeyPrefix,\n\t});\n\n\tconst sleepMs = (ms: number): Promise<void> =>\n\t\tms <= 0\n\t\t\t? Promise.resolve()\n\t\t\t: new Promise<void>((resolve) => {\n\t\t\t\t\tconst t = new ResettableTimer();\n\t\t\t\t\tt.start(ms, () => resolve());\n\t\t\t\t});\n\n\t// Singleflight — concurrent cache-miss requests with the same key share one\n\t// upstream call. `keyFn` must be synchronous (singleflight needs the key\n\t// before dispatching), so we compute the key eagerly in `invoke`/`stream`\n\t// and thread it through as `_precomputedKey`. The passed `keyFn` reads\n\t// that precomputed value instead of re-hashing.\n\tconst upstreamInFlight = singleFromAny<ResolveArgsWithKey, LLMResponse>(\n\t\tasync ({ messages, invokeOpts }) => {\n\t\t\treturn await firstValueFrom(fromAny(inner.invoke(messages, invokeOpts)));\n\t\t},\n\t\t{ keyFn: ({ _precomputedKey }) => _precomputedKey },\n\t);\n\n\tconst wrap = adapterWrapper(inner, {\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst key = await cache.keyFor(messages, invokeOpts);\n\t\t\tconst entry = await cache.lookup(messages, invokeOpts);\n\t\t\tif (entry?.response) {\n\t\t\t\tconst cached = entry.response;\n\t\t\t\treturn { ...cached, metadata: { ...(cached.metadata ?? {}), replayCache: \"hit\" } };\n\t\t\t}\n\n\t\t\tif (mode === \"read-strict\") throw new ReplayCacheMissError(key, \"invoke\");\n\t\t\tconst resp = await upstreamInFlight({ messages, invokeOpts, _precomputedKey: key });\n\t\t\tif (!isReadOnly) {\n\t\t\t\tawait cache.store(messages, invokeOpts, { response: resp, storedAtNs: wallClockNs() });\n\t\t\t}\n\t\t\treturn resp;\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tif (!cacheStreaming) {\n\t\t\t\t// `read-strict` only applies to cache-checked paths. When\n\t\t\t\t// `cacheStreaming: false` the cache isn't consulted for\n\t\t\t\t// streams at all, so passthrough is correct — throwing would\n\t\t\t\t// make the adapter's stream() permanently unusable.\n\t\t\t\tfor await (const delta of inner.stream(messages, invokeOpts)) yield delta;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst key = await cache.keyFor(messages, invokeOpts);\n\t\t\tconst entry = await cache.lookup(messages, invokeOpts);\n\t\t\tif (entry) {\n\t\t\t\tconst cached = entry.response;\n\t\t\t\t// Cadence-faithful replay when both recorded chunks + delays are present.\n\t\t\t\tif (entry.streamChunks && entry.streamCadenceMs) {\n\t\t\t\t\tfor (let i = 0; i < entry.streamChunks.length; i++) {\n\t\t\t\t\t\tconst delay = entry.streamCadenceMs[i] ?? 0;\n\t\t\t\t\t\tconst effective = replaySpeed > 0 ? delay / replaySpeed : 0;\n\t\t\t\t\t\tif (effective > 0) await sleepMs(effective);\n\t\t\t\t\t\tyield { type: \"token\", delta: entry.streamChunks[i]?.delta ?? \"\" };\n\t\t\t\t\t}\n\t\t\t\t} else if (cached.content) {\n\t\t\t\t\tyield { type: \"token\", delta: cached.content };\n\t\t\t\t}\n\t\t\t\tif (cached.usage) yield { type: \"usage\", usage: cached.usage };\n\t\t\t\tyield { type: \"finish\", reason: cached.finishReason ?? \"stop\" };\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (mode === \"read-strict\") throw new ReplayCacheMissError(key, \"stream\");\n\t\t\t// Miss: accumulate, store, re-yield.\n\t\t\tlet content = \"\";\n\t\t\tlet usage: LLMResponse[\"usage\"] | undefined;\n\t\t\tlet finishReason: string | undefined;\n\t\t\tconst chunks: { delta: string }[] = [];\n\t\t\tconst delaysMs: number[] = [];\n\t\t\t// Time-to-first-token (TTFT — provider latency / network / queue\n\t\t\t// warmup) is NOT cadence; setting lastNs inside the loop on first\n\t\t\t// chunk means chunk-0's delay is 0 (boundary-clean) and subsequent\n\t\t\t// delays measure only inter-chunk gaps. Use the central clock so\n\t\t\t// the scale matches every other cadence measurement in the library\n\t\t\t// and the module stays browser-safe (spec §5.11).\n\t\t\tlet lastNs: number | undefined;\n\t\t\tfor await (const delta of inner.stream(messages, invokeOpts)) {\n\t\t\t\tif (delta.type === \"token\") {\n\t\t\t\t\tcontent += delta.delta;\n\t\t\t\t\tif (captureStreamCadence) {\n\t\t\t\t\t\tconst now = monotonicNs();\n\t\t\t\t\t\tconst gap = lastNs === undefined ? 0 : (now - lastNs) / 1e6;\n\t\t\t\t\t\tdelaysMs.push(gap);\n\t\t\t\t\t\tlastNs = now;\n\t\t\t\t\t\tchunks.push({ delta: delta.delta });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (delta.type === \"usage\") usage = delta.usage;\n\t\t\t\tif (delta.type === \"finish\") finishReason = delta.reason;\n\t\t\t\tyield delta;\n\t\t\t}\n\t\t\tif ((content || usage) && !isReadOnly) {\n\t\t\t\tconst resp: LLMResponse = {\n\t\t\t\t\tcontent,\n\t\t\t\t\tusage: usage ?? { input: { regular: 0 }, output: { regular: 0 } },\n\t\t\t\t\tfinishReason,\n\t\t\t\t\tmodel: inner.model ?? invokeOpts?.model ?? \"\",\n\t\t\t\t\tprovider: inner.provider,\n\t\t\t\t};\n\t\t\t\tconst entryToStore: CachedEntry = {\n\t\t\t\t\tresponse: resp,\n\t\t\t\t\tstoredAtNs: wallClockNs(),\n\t\t\t\t\t...(captureStreamCadence ? { streamChunks: chunks, streamCadenceMs: delaysMs } : {}),\n\t\t\t\t};\n\t\t\t\tawait cache.store(messages, invokeOpts, entryToStore);\n\t\t\t}\n\t\t},\n\t});\n\twithLayer(wrap, \"withReplayCache\", inner);\n\treturn wrap;\n}\n\n// canonicalJson is no longer re-exported here — consumers import directly from\n// @graphrefly/pure-ts/extra. The presentation-layer re-export caused a\n// duplicate-export conflict at the root barrel level (A3 build gate).\n","/**\n * `singleFromAny` — keyed promise/Node de-duplication (\"singleflight\").\n *\n * Given a `factory: (key) => NodeInput<T>`, returns a callable that dedupes\n * concurrent invocations sharing the same key — all callers with the same\n * key while a request is in-flight receive the same `Promise<T>`. Once the\n * underlying source settles (DATA, ERROR, or COMPLETE), the cache entry is\n * cleared so the next call re-invokes the factory.\n *\n * This is the classic \"singleflight\" pattern from Go, generalised over the\n * library's `NodeInput<T>` bridge so callers can pass Promise-returning\n * factories, Node-returning factories, or plain value factories with\n * identical semantics.\n *\n * Use cases:\n * - `withReplayCache` cache-miss thundering-herd dedup\n * - Shared HTTP fetches keyed by URL\n * - Expensive compute keyed by request fingerprint\n *\n * @example\n * ```ts\n * const fetchUser = singleFromAny<string, User>((id) => fetch(`/users/${id}`).then(r => r.json()));\n * // Two concurrent callers with id=\"42\" → one underlying fetch, two Promises resolving to the same User.\n * const [a, b] = await Promise.all([fetchUser(\"42\"), fetchUser(\"42\")]);\n * ```\n *\n * @category extra\n */\n\nimport type { Node } from \"@graphrefly/pure-ts/core\";\nimport { COMPLETE, ERROR } from \"@graphrefly/pure-ts/core\";\n// Import directly from the source sub-files (rather than the `./sources.js`\n// barrel) so the `single-from-any` module is NOT part of any cycle that runs\n// through `extra/sources/index.ts` — eager re-exports through the barrel were\n// observed to leave `firstValueFrom` / `keepalive` unresolved during nested\n// import chains under vite-node.\nimport { fromAny, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { firstValueFrom } from \"../sources/settled.js\";\n\nexport interface SingleFromAnyOptions<K> {\n\t/**\n\t * Convert a typed key into a cache-string. Defaults to `String(key)`, which\n\t * works for primitive keys; callers with object keys should provide a\n\t * stable serializer (e.g., canonical JSON).\n\t */\n\tkeyFn?: (key: K) => string;\n}\n\n/**\n * Dedupe concurrent `factory(key)` invocations. Returns a bound callable.\n *\n * @param factory - Produces a `NodeInput<T>` for each unique key.\n * @param opts - Optional key-stringification.\n * @returns A function `(key: K) => Promise<T>` whose inflight results are shared per key.\n */\nexport function singleFromAny<K, T>(\n\tfactory: (key: K) => NodeInput<T>,\n\topts: SingleFromAnyOptions<K> = {},\n): (key: K) => Promise<T> {\n\tconst keyFn = opts.keyFn ?? ((k: K) => String(k));\n\tconst inFlight = new Map<string, Promise<T>>();\n\n\treturn (key: K): Promise<T> => {\n\t\tconst k = keyFn(key);\n\t\tconst existing = inFlight.get(k);\n\t\tif (existing) return existing;\n\n\t\tconst input = factory(key);\n\n\t\t// Resolve the NodeInput to a Promise<T>. Different input shapes need\n\t\t// different bridges — Promise/Node/AsyncIterable/Iterable/plain value.\n\t\tlet rawPromise: Promise<T>;\n\t\tif (input != null && typeof (input as PromiseLike<T>).then === \"function\") {\n\t\t\trawPromise = Promise.resolve(input as PromiseLike<T>);\n\t\t} else if (\n\t\t\tinput != null &&\n\t\t\ttypeof input === \"object\" &&\n\t\t\t\"subscribe\" in (input as object) &&\n\t\t\t\"cache\" in (input as object)\n\t\t) {\n\t\t\t// Node: bridge via firstValueFrom.\n\t\t\trawPromise = firstValueFrom(input as Node<T>);\n\t\t} else if (\n\t\t\tinput != null &&\n\t\t\ttypeof input === \"object\" &&\n\t\t\tSymbol.asyncIterator in (input as object)\n\t\t) {\n\t\t\t// AsyncIterable — take the first value, then close the iterator so\n\t\t\t// any owned resources (HTTP body, subscription, timer) are released.\n\t\t\trawPromise = (async () => {\n\t\t\t\tconst iter = (input as AsyncIterable<T>)[Symbol.asyncIterator]();\n\t\t\t\ttry {\n\t\t\t\t\tconst { value, done } = await iter.next();\n\t\t\t\t\tif (done) throw new Error(\"singleFromAny: factory returned empty async iterable\");\n\t\t\t\t\treturn value as T;\n\t\t\t\t} finally {\n\t\t\t\t\tawait iter.return?.();\n\t\t\t\t}\n\t\t\t})();\n\t\t} else if (input != null && typeof input === \"object\" && Symbol.iterator in (input as object)) {\n\t\t\t// Iterable — take the first value, close the iterator.\n\t\t\trawPromise = (async () => {\n\t\t\t\tconst iter = (input as Iterable<T>)[Symbol.iterator]();\n\t\t\t\ttry {\n\t\t\t\t\tconst { value, done } = iter.next();\n\t\t\t\t\tif (done) throw new Error(\"singleFromAny: factory returned empty iterable\");\n\t\t\t\t\treturn value as T;\n\t\t\t\t} finally {\n\t\t\t\t\titer.return?.();\n\t\t\t\t}\n\t\t\t})();\n\t\t} else {\n\t\t\t// Plain value.\n\t\t\trawPromise = Promise.resolve(input as T);\n\t\t}\n\n\t\t// Install the cache entry BEFORE attaching `.finally`. Otherwise a\n\t\t// sync-resolved Promise's finally microtask could run before the\n\t\t// `inFlight.set` below, leaving a stale entry installed afterwards.\n\t\t// We wrap in a holder whose reference we capture *before* chaining.\n\t\tlet tracked!: Promise<T>;\n\t\tconst cleanup = (): void => {\n\t\t\tif (inFlight.get(k) === tracked) inFlight.delete(k);\n\t\t};\n\t\ttracked = rawPromise.then(\n\t\t\t(v) => {\n\t\t\t\tcleanup();\n\t\t\t\treturn v;\n\t\t\t},\n\t\t\t(e) => {\n\t\t\t\tcleanup();\n\t\t\t\tthrow e;\n\t\t\t},\n\t\t);\n\t\tinFlight.set(k, tracked);\n\t\treturn tracked;\n\t};\n}\n\n/**\n * Reactive variant: returns a bound callable that hands out `Node<T>` values.\n * All concurrent callers with the same key during an in-flight source share\n * the same Node. When the underlying source **terminally** settles (ERROR\n * or COMPLETE), the Node is removed from the cache so the next call\n * re-invokes `factory`. DATA is NOT terminal — callers subscribing after\n * the first DATA still receive the shared Node (and push-on-subscribe per\n * the spec's cached-DATA contract).\n *\n * Use when downstream wants reactive subscription (not a one-shot Promise).\n *\n * @category extra\n */\nexport function singleNodeFromAny<K, T>(\n\tfactory: (key: K) => NodeInput<T>,\n\topts: SingleFromAnyOptions<K> = {},\n): (key: K) => Node<T> {\n\tconst keyFn = opts.keyFn ?? ((k: K) => String(k));\n\tconst inFlight = new Map<string, Node<T>>();\n\n\treturn (key: K): Node<T> => {\n\t\tconst k = keyFn(key);\n\t\tconst existing = inFlight.get(k);\n\t\tif (existing) return existing;\n\n\t\tconst node = fromAny(factory(key));\n\t\tinFlight.set(k, node);\n\n\t\t// Evict on terminal settle only — ERROR or COMPLETE. DATA is a value\n\t\t// emission, not a lifecycle transition; multi-emitting Nodes should\n\t\t// continue to share across subscribers after the first value.\n\t\tconst unsub = node.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === ERROR || m[0] === COMPLETE) {\n\t\t\t\t\tif (inFlight.get(k) === node) inFlight.delete(k);\n\t\t\t\t\tunsub();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn node;\n\t};\n}\n","/**\n * Settled/signal helpers.\n *\n * Moved from extra/sources/settled.ts during cleave A2.\n * `keepalive` is substrate — it lives at `@graphrefly/pure-ts`\n * (`packages/pure-ts/src/extra/sources/_keepalive.ts`), not here.\n */\n\n/**\n * Settled / signal helpers — boundary primitives for converting reactive\n * sources into Promise/AbortSignal endpoints.\n *\n * - {@link firstValueFrom} / {@link firstWhere} — Promise of the first\n * matching DATA.\n * - {@link awaitSettled} — composition over `firstWhere` + reactive\n * `timeout` from `extra/resilience` (lazy import to avoid a\n * resilience → sources cycle).\n * - {@link nodeSignal} — `Node<boolean>` → `AbortSignal` bridge.\n * - {@link reactiveCounter} — capped counter exposed as a `Node<number>`.\n */\n\nimport {\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tERROR,\n\ttype Messages,\n\ttype Node,\n\tnode,\n} from \"@graphrefly/pure-ts/core\";\n\n/**\n * Converts the first `DATA` on `source` into a Promise; rejects on `ERROR` or `COMPLETE` without data.\n *\n * **Important:** This subscribes and waits for a **future** emission. Data that\n * has already flowed is gone and will not be seen. Call this *before* the upstream\n * emits, or use `source.cache` / `source.status` for already-cached state.\n * See COMPOSITION-GUIDE §2 (subscription ordering).\n *\n * @param source - Node to read once.\n * @returns Promise of the first value.\n *\n * @example\n * ```ts\n * import { firstValueFrom, of } from \"@graphrefly/graphrefly-ts\";\n *\n * await firstValueFrom(of(42));\n * ```\n *\n * @category extra\n */\nexport function firstValueFrom<T>(source: Node<T>): Promise<T> {\n\treturn new Promise<T>((resolve, reject) => {\n\t\tlet settled = false;\n\t\tlet shouldUnsub = false;\n\t\tlet unsub: (() => void) | undefined;\n\t\tunsub = source.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (settled) return;\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\tresolve(m[1] as T);\n\t\t\t\t\tif (unsub) {\n\t\t\t\t\t\tunsub();\n\t\t\t\t\t\tunsub = undefined;\n\t\t\t\t\t} else shouldUnsub = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (m[0] === ERROR) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\treject(m[1]);\n\t\t\t\t\tif (unsub) {\n\t\t\t\t\t\tunsub();\n\t\t\t\t\t\tunsub = undefined;\n\t\t\t\t\t} else shouldUnsub = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (m[0] === COMPLETE) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\treject(new Error(\"completed without DATA\"));\n\t\t\t\t\tif (unsub) {\n\t\t\t\t\t\tunsub();\n\t\t\t\t\t\tunsub = undefined;\n\t\t\t\t\t} else shouldUnsub = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tif (shouldUnsub) {\n\t\t\tunsub?.();\n\t\t\tunsub = undefined;\n\t\t}\n\t});\n}\n\n/**\n * Wait for the first DATA value from `source` that satisfies `predicate`.\n *\n * Subscribes directly and resolves on the first DATA value where\n * `predicate` returns true. Reactive, no polling. Use in tests and\n * bridging code where you need a single matching value as a Promise.\n *\n * **Important:** This only captures **future** emissions — data that has\n * already flowed through the node is gone. Call this *before* the upstream\n * emits. For already-cached values, use `source.cache` / `source.status`.\n * See COMPOSITION-GUIDE §2 (subscription ordering).\n *\n * ```ts\n * const val = await firstWhere(strategy.snapshot, snap => snap.size > 0);\n * ```\n *\n * @param source - Upstream node to observe.\n * @param predicate - Returns `true` for the value to resolve on.\n * @param opts - `{ skipCurrent?: boolean }`. When `skipCurrent: true`, any DATA\n * delivered during the synchronous `subscribe()` call (push-on-subscribe §2.2\n * replay of the cached value) is ignored — the promise resolves only on the\n * next future emission. Useful when the caller wants to await the next\n * settlement event after an imperative action (e.g. `run()` minting a new\n * runVersion, where the currently-cached value belongs to the previous run).\n *\n * @category extra\n */\nexport function firstWhere<T>(\n\tsource: Node<T>,\n\tpredicate: (value: T) => boolean,\n\topts?: { skipCurrent?: boolean; kick?: () => void },\n): Promise<T> {\n\t// Lock 3.A (Phase 13.6.B): subscribe synchronously inside the function\n\t// body — NOT inside the Promise executor. Subscribing inside the\n\t// executor would defer the subscription past any synchronous `kick()`\n\t// the caller fires after the call returns, race-losing the very wave\n\t// the caller wants to observe.\n\t//\n\t// To bridge sync-subscribe with the async Promise contract, we record\n\t// any settlement that fires *before* the Promise constructor runs, and\n\t// the executor immediately resolves/rejects with the recorded value.\n\t// Settlements after the executor runs go straight through resolve/reject.\n\ttype Pending =\n\t\t| { kind: \"data\"; value: T }\n\t\t| { kind: \"error\"; err: unknown }\n\t\t| { kind: \"complete\" };\n\tlet pending: Pending | undefined;\n\tlet resolveFn: ((value: T) => void) | undefined;\n\tlet rejectFn: ((err: unknown) => void) | undefined;\n\tlet settled = false;\n\tlet shouldUnsub = false;\n\tlet unsub: (() => void) | undefined;\n\tlet inInitialSyncPhase = opts?.skipCurrent === true;\n\n\t// QA P1: every settler short-circuits when `settled === true` so a\n\t// later settle attempt (e.g. `kick()` throwing AFTER it synchronously\n\t// fired matching DATA, OR a `[DATA matched, ERROR]` wave during\n\t// push-on-subscribe) cannot overwrite an earlier `pending` outcome.\n\t// Without this gate, a kick that races sink-callback settlement could\n\t// reject a Promise the user already has resolved-DATA for.\n\tconst settleData = (v: T): void => {\n\t\tif (settled) return;\n\t\tsettled = true;\n\t\tif (resolveFn != null) resolveFn(v);\n\t\telse pending = { kind: \"data\", value: v };\n\t};\n\tconst settleError = (err: unknown): void => {\n\t\tif (settled) return;\n\t\tsettled = true;\n\t\tif (rejectFn != null) rejectFn(err);\n\t\telse pending = { kind: \"error\", err };\n\t};\n\tconst settleComplete = (): void => {\n\t\tif (settled) return;\n\t\tsettled = true;\n\t\tconst err = new Error(\"completed without matching value\");\n\t\tif (rejectFn != null) rejectFn(err);\n\t\telse pending = { kind: \"complete\" };\n\t};\n\tconst detach = (): void => {\n\t\tif (unsub) {\n\t\t\tunsub();\n\t\t\tunsub = undefined;\n\t\t} else shouldUnsub = true;\n\t};\n\n\tconst sink: (msgs: Messages) => void = (msgs) => {\n\t\tif (settled) return;\n\t\tfor (const m of msgs) {\n\t\t\tif (settled) return;\n\t\t\t// During the initial sync phase, swallow only cached DATA\n\t\t\t// (push-on-subscribe §2.2). Terminal ERROR / COMPLETE must\n\t\t\t// still reject the promise — otherwise an already-terminated\n\t\t\t// source synchronously delivering `[[ERROR, ...]]` or\n\t\t\t// `[[COMPLETE]]` during `subscribe()` would hang forever\n\t\t\t// under `skipCurrent: true`.\n\t\t\tif (inInitialSyncPhase && m[0] === DATA) continue;\n\t\t\tif (m[0] === DATA) {\n\t\t\t\tconst v = m[1] as T;\n\t\t\t\tif (predicate(v)) {\n\t\t\t\t\tsettleData(v);\n\t\t\t\t\tdetach();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (m[0] === ERROR) {\n\t\t\t\tsettleError(m[1]);\n\t\t\t\tdetach();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (m[0] === COMPLETE) {\n\t\t\t\tsettleComplete();\n\t\t\t\tdetach();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t};\n\tunsub = source.subscribe(sink);\n\tinInitialSyncPhase = false;\n\t// Lock 3.A: fire `kick` AFTER subscribe is in place. With sync\n\t// subscribe + sync kick, the resulting wave reaches `sink` before\n\t// control returns — making subscribe-before-kick ordering structurally\n\t// impossible to misuse.\n\tif (opts?.kick != null && !settled) {\n\t\ttry {\n\t\t\topts.kick();\n\t\t} catch (err) {\n\t\t\tsettleError(err);\n\t\t\tdetach();\n\t\t}\n\t}\n\tif (shouldUnsub) {\n\t\tunsub?.();\n\t\tunsub = undefined;\n\t}\n\n\treturn new Promise<T>((resolve, reject) => {\n\t\t// If a settlement landed synchronously before the executor runs,\n\t\t// flush it through immediately.\n\t\tif (pending != null) {\n\t\t\tif (pending.kind === \"data\") resolve(pending.value);\n\t\t\telse if (pending.kind === \"error\") reject(pending.err);\n\t\t\telse reject(new Error(\"completed without matching value\"));\n\t\t\treturn;\n\t\t}\n\t\tresolveFn = resolve;\n\t\trejectFn = reject;\n\t});\n}\n\n/**\n * Await the first non-nullish DATA value from `source`, with optional\n * timeout. Composition sugar over `firstWhere` + reactive timeout.\n *\n * Designed as the CLI/boundary sink for reactive pipelines that end in a\n * nullable node (e.g. `promptNode` — per COMPOSITION-GUIDE §8, it emits\n * `null` before it settles with a real value). Replaces the common pattern\n * `firstValueFrom(filter(source, v => v != null))` with a deadline.\n *\n * - Rejects with `TimeoutError` (from `extra/resilience`) if no matching\n * value arrives within `timeoutMs`. Omit `timeoutMs` for unbounded wait.\n * - `predicate` defaults to `v => v != null`. Pass a custom predicate to\n * gate on a stronger condition (e.g. `v => typeof v === \"string\"`).\n * - Pass `skipCurrent: true` to ignore the currently-cached value delivered\n * synchronously via push-on-subscribe and resolve only on the *next*\n * matching emission. Useful after an imperative action that should produce\n * a fresh settlement (e.g. `run()` minting a new version — the stale\n * cached value from the previous run must not resolve the new caller).\n *\n * ```ts\n * const brief = await awaitSettled(briefNode, { timeoutMs: 120_000 });\n * // or with a predicate:\n * const rich = await awaitSettled(node, {\n * predicate: (v): v is MyShape => typeof v === \"object\" && v != null && \"key\" in v,\n * timeoutMs: 60_000,\n * });\n * // or after kicking off a fresh run:\n * kickOff();\n * const fresh = await awaitSettled(resultNode, { skipCurrent: true });\n * ```\n *\n * Reactive inside, sync propagation — the one async boundary is the\n * returned `Promise<T>` (spec §5.10: async belongs at sources and\n * boundaries, not in the graph).\n *\n * @param source - Upstream node to observe.\n * @param opts - `{ predicate?, timeoutMs?, skipCurrent? }`.\n * @returns Promise that resolves with the first matching value, or rejects on timeout / ERROR / COMPLETE-without-DATA.\n *\n * @category extra\n */\n// Lazy module-cache for the `withTimeout` resilience operator. The dynamic\n// import keeps `settled` free of an eager edge into the resilience family;\n// first call pays the one-shot import, subsequent calls hit cached refs.\nlet _timeoutOp: typeof import(\"../resilience/timeout.js\").withTimeout | undefined;\nlet _nsPerMs: number | undefined;\n\nexport async function awaitSettled<T>(\n\tsource: Node<T>,\n\topts?: {\n\t\tpredicate?: (value: T) => boolean;\n\t\ttimeoutMs?: number;\n\t\tskipCurrent?: boolean;\n\t\t/**\n\t\t * Lock 3.A (Phase 13.6.B): fired AFTER subscribe is in place but\n\t\t * BEFORE the helper's async boundary is exposed to the caller.\n\t\t * Subscribe-before-kick is structurally enforced — the kick's\n\t\t * synchronous wave reaches `sink` before control returns. Replaces\n\t\t * the prior load-bearing-comment pattern (M.20-load-bearing) with\n\t\t * a misuse-impossible API shape.\n\t\t *\n\t\t * Common pattern:\n\t\t * await awaitSettled(node, {\n\t\t * skipCurrent: true,\n\t\t * kick: () => producer.emit(value),\n\t\t * });\n\t\t *\n\t\t * Omit `kick` for external-trigger cases where the wave is fired\n\t\t * by code outside the helper's caller; subscribe still lands\n\t\t * synchronously inside the helper body so the next external wave\n\t\t * is not lost.\n\t\t */\n\t\tkick?: () => void;\n\t},\n): Promise<NonNullable<T>> {\n\tconst predicate = opts?.predicate ?? ((v: T) => v != null);\n\tconst skipCurrent = opts?.skipCurrent;\n\tconst kick = opts?.kick;\n\tif (opts?.timeoutMs == null || opts.timeoutMs <= 0) {\n\t\treturn (await firstWhere(source, predicate, { skipCurrent, kick })) as NonNullable<T>;\n\t}\n\t// Reactive composition: `timeout()` wraps the source as a Node that\n\t// emits ERROR(TimeoutError) on deadline. `firstWhere` then resolves on\n\t// the first matching DATA or rejects on that ERROR. One async boundary\n\t// (the returned Promise), everything inside is sync reactive.\n\tif (_timeoutOp === undefined) {\n\t\tconst [timeoutMod, backoff] = await Promise.all([\n\t\t\timport(\"../resilience/timeout.js\"),\n\t\t\timport(\"../resilience/backoff.js\"),\n\t\t]);\n\t\t_timeoutOp = timeoutMod.withTimeout;\n\t\t_nsPerMs = backoff.NS_PER_MS;\n\t}\n\tconst guarded = _timeoutOp(source, { ns: opts.timeoutMs * (_nsPerMs as number) }).node;\n\treturn (await firstWhere(guarded, predicate, { skipCurrent, kick })) as NonNullable<T>;\n}\n\n/**\n * Converts a reactive `Node<boolean>` into a browser-standard `AbortSignal`\n * that fires when the node settles on `true`. Useful for threading a reactive\n * \"cancel\" flag into any async boundary that accepts a signal (fetch, LLM SDK\n * calls, child-process APIs, timers).\n *\n * **Contract.**\n * - `signal.abort(reason)` fires exactly once, on the first DATA emission with\n * a truthy value. Subsequent emissions are ignored (AbortSignal is\n * single-shot).\n * - Null / `false` / sentinel values are ignored. Push-on-subscribe will\n * check the currently-cached value on subscribe and abort immediately if\n * it's already `true`.\n * - `reason` defaults to `\"cancelled via nodeSignal\"`; pass `opts.reason` to\n * override (`DOMException`, `Error`, or any value accepted by\n * `AbortController.abort`).\n *\n * **Lifecycle.**\n * - Returns a `{signal, dispose}` bundle. Call `dispose()` when you're done\n * with the signal (e.g. in a `finally` after the async operation completes).\n * `dispose()` unsubscribes from the node and is a no-op once the signal has\n * fired.\n * - **Memory note:** without `dispose()` the subscription keeps the reactive\n * node alive for the lifetime of the process. For bridge calls inside a\n * `switchMap` project fn, the switchMap supersede tears the inner subgraph\n * down, which is usually the right lifetime — but still call `dispose()`\n * from the caller's `finally` for clarity.\n *\n * @example\n * ```ts\n * const aborted = state(false);\n * const { signal, dispose } = nodeSignal(aborted);\n * try {\n * const resp = await adapter.invoke(msgs, { signal });\n * return resp;\n * } finally {\n * dispose();\n * }\n * ```\n *\n * @category extra\n */\nexport function nodeSignal(\n\tsource: Node<boolean>,\n\topts?: { reason?: unknown },\n): { signal: AbortSignal; dispose: () => void } {\n\tconst ctrl = new AbortController();\n\tconst reason = opts?.reason ?? new Error(\"cancelled via nodeSignal\");\n\tlet unsub: (() => void) | undefined;\n\tlet shouldUnsub = false;\n\tconst done = () => {\n\t\tif (unsub) {\n\t\t\tunsub();\n\t\t\tunsub = undefined;\n\t\t} else shouldUnsub = true;\n\t};\n\tunsub = source.subscribe((msgs) => {\n\t\tif (ctrl.signal.aborted) return;\n\t\tfor (const m of msgs) {\n\t\t\tif (m[0] === DATA && m[1] === true) {\n\t\t\t\tctrl.abort(reason);\n\t\t\t\tdone();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (m[0] === ERROR) {\n\t\t\t\t// Treat an ERROR on the abort source as a cancel signal too —\n\t\t\t\t// a broken control channel should fail closed, not leak the\n\t\t\t\t// in-flight call. Use the error as the abort reason.\n\t\t\t\tctrl.abort(m[1]);\n\t\t\t\tdone();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (m[0] === COMPLETE) {\n\t\t\t\t// Source completed without aborting — no-op. `done()` already\n\t\t\t\t// released the subscription here, so a later `dispose()` call\n\t\t\t\t// from the caller is a no-op (safe / idempotent).\n\t\t\t\tdone();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t});\n\tif (shouldUnsub) {\n\t\tunsub?.();\n\t\tunsub = undefined;\n\t}\n\treturn {\n\t\tsignal: ctrl.signal,\n\t\tdispose: () => {\n\t\t\tif (unsub) {\n\t\t\t\tunsub();\n\t\t\t\tunsub = undefined;\n\t\t\t}\n\t\t},\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// reactiveCounter\n// ---------------------------------------------------------------------------\n\n/** Bundle returned by {@link reactiveCounter}. */\nexport type ReactiveCounterBundle = {\n\t/** Reactive node holding the current count. */\n\treadonly node: Node<number>;\n\t/** Increment by 1. Returns `false` if cap would be exceeded. */\n\tincrement(): boolean;\n\t/** Current count (synchronous read). */\n\tget(): number;\n\t/** Whether the counter has reached its cap. */\n\tatCap(): boolean;\n};\n\n/**\n * Reactive counter with a cap — the building block for circuit breakers.\n *\n * Wraps a `state(0)` node with `increment()` that respects a maximum.\n * The `node` is subscribable and composable like any reactive node. When\n * the cap is reached, `increment()` returns `false`.\n *\n * ```ts\n * const retries = reactiveCounter(10);\n * retries.increment(); // true — count is now 1\n * retries.node.subscribe(...); // reactive updates\n * retries.atCap(); // false\n * ```\n *\n * @param cap - Maximum value (inclusive). 0 = no increments allowed.\n * @category extra\n */\nexport function reactiveCounter(cap: number): ReactiveCounterBundle {\n\tconst counter = node([], { initial: 0 });\n\treturn {\n\t\tnode: counter,\n\t\tincrement() {\n\t\t\tconst current = counter.cache ?? 0;\n\t\t\tif (current >= cap) return false;\n\t\t\tcounter.down([[DIRTY], [DATA, current + 1]]);\n\t\t\treturn true;\n\t\t},\n\t\tget() {\n\t\t\treturn counter.cache ?? 0;\n\t\t},\n\t\tatCap() {\n\t\t\treturn (counter.cache ?? 0) >= cap;\n\t\t},\n\t};\n}\n","/**\n * LLM-specific content-addressed cache wrapper over the generic\n * {@link contentAddressedStorage} substrate in `src/extra/`. Handles the\n * ChatMessage + LLMInvokeOptions → stable key shape that both\n * `withReplayCache` and `fallbackAdapter` need, so the two middleware files\n * don't drift on key construction.\n *\n * The generic substrate does the sha256 + canonicalJson + tier IO; this\n * wrapper owns:\n * - Stripping non-serializable `signal` (AbortSignal) and `keyContext`\n * (caller-opaque context) from the default key.\n * - Arity-dispatched legacy `keyFn` support (1-arg ctx-object form vs 2-arg\n * `(messages, opts)` form).\n * - LLM-conventional `llm-replay` default key prefix (override via `keyPrefix`).\n *\n * @module\n */\n\nimport type { KvStorageTier } from \"@graphrefly/pure-ts/extra\";\nimport {\n\ttype ContentAddressedMode,\n\ttype ContentAddressedStorage,\n\tcontentAddressedStorage,\n} from \"@graphrefly/pure-ts/extra\";\nimport type { ChatMessage, LLMInvokeOptions } from \"../core/types.js\";\n\n/**\n * Context object passed to the 1-arg {@link ContentAddressedCacheOptions.keyFn}\n * form. Adding fields here is forward-compatible — existing 1-arg consumers\n * that ignore unknowns keep working.\n */\nexport interface LLMCacheKeyContext {\n\treadonly messages: readonly ChatMessage[];\n\treadonly opts: LLMInvokeOptions | undefined;\n\t/** Shortcut to `opts?.keyContext` — no extra guard in callers. */\n\treadonly context: unknown;\n}\n\nexport interface ContentAddressedCacheOptions<V> {\n\tstorage: KvStorageTier;\n\tmode?: ContentAddressedMode;\n\t/**\n\t * Custom key function. Receives either {@link LLMCacheKeyContext} (1-arg\n\t * form) or `(messages, opts?)` (legacy 2-arg form) — the wrapper dispatches\n\t * on `Function.length`. Return `string` or `Promise<string>`.\n\t */\n\tkeyFn?:\n\t\t| ((ctx: LLMCacheKeyContext) => string | Promise<string>)\n\t\t| ((messages: readonly ChatMessage[], opts?: LLMInvokeOptions) => string | Promise<string>);\n\t/** Prefix applied as `${keyPrefix}:${hash}`. Default `\"llm-replay\"`. */\n\tkeyPrefix?: string;\n\t/**\n\t * Optional value type hint — callers may store anything JSON-serializable.\n\t * `withReplayCache` stores `CachedEntry` (response + stream cadence);\n\t * `fallbackAdapter` stores the raw `LLMResponse`.\n\t */\n\t_valueType?: V;\n}\n\n/** Handle returned by {@link contentAddressedCache}. */\nexport interface ContentAddressedCache<V> {\n\tkeyFor(messages: readonly ChatMessage[], invokeOpts?: LLMInvokeOptions): Promise<string>;\n\tlookup(messages: readonly ChatMessage[], invokeOpts?: LLMInvokeOptions): Promise<V | undefined>;\n\tstore(\n\t\tmessages: readonly ChatMessage[],\n\t\tinvokeOpts: LLMInvokeOptions | undefined,\n\t\tvalue: V,\n\t): Promise<void>;\n\tforget(messages: readonly ChatMessage[], invokeOpts?: LLMInvokeOptions): Promise<void>;\n}\n\n/**\n * Builds an LLM-shaped content-addressed cache over `storage`. Default keying\n * hashes `(messages, opts minus signal/keyContext)` via\n * {@link contentAddressedStorage} — the generic extra-tier substrate.\n *\n * Used by `withReplayCache` (full response cache) and `fallbackAdapter`\n * (fixture lookup). Both consumers wrap this to add their divergent features\n * (singleflight / stream cadence / canned miss response) around the shared\n * substrate.\n *\n * @category internal\n */\nexport function contentAddressedCache<V>(\n\topts: ContentAddressedCacheOptions<V>,\n): ContentAddressedCache<V> {\n\tconst { storage, mode = \"read-write\", keyFn, keyPrefix = \"llm-replay\" } = opts;\n\n\t// Substrate mode: translate `\"read-strict\"` to `\"read\"` so the substrate\n\t// returns `undefined` on miss. The LLM-middleware callers (`withReplayCache`,\n\t// `fallbackAdapter`) own the strict-mode throw because they emit\n\t// domain-specific error types (`ReplayCacheMissError` / `FallbackMissError`)\n\t// that carry context the substrate shouldn't know about.\n\tconst substrateMode = mode === \"read-strict\" ? \"read\" : mode;\n\n\t// When `keyFn` is supplied, we wire it through the substrate's raw-key API\n\t// (via a synthesized keyContext passthrough). When omitted, we let the\n\t// substrate hash the default shape (messages + opts minus non-serializable\n\t// fields) with the standard prefix.\n\tconst substrate: ContentAddressedStorage<\n\t\t{ messages: readonly ChatMessage[]; opts: LLMInvokeOptions | undefined },\n\t\tV\n\t> = contentAddressedStorage({\n\t\tstorage,\n\t\tkeyPrefix,\n\t\tmode: substrateMode,\n\t\tkeyContext: ({ messages, opts: invokeOpts }) => {\n\t\t\t// Drop `signal` (not serializable) and `keyContext` (caller-opaque\n\t\t\t// context should only participate when user opts in via keyFn).\n\t\t\tconst { signal: _signal, keyContext: _keyContext, ...rest } = invokeOpts ?? {};\n\t\t\treturn { messages, opts: rest };\n\t\t},\n\t});\n\n\tasync function keyFor(\n\t\tmessages: readonly ChatMessage[],\n\t\tinvokeOpts?: LLMInvokeOptions,\n\t): Promise<string> {\n\t\tif (keyFn) {\n\t\t\t// Arity-dispatch: Function.length === 1 → ctx-object form;\n\t\t\t// otherwise → legacy 2-arg (messages, opts). Both may return\n\t\t\t// sync or async strings.\n\t\t\tif (keyFn.length <= 1) {\n\t\t\t\tconst ctx: LLMCacheKeyContext = {\n\t\t\t\t\tmessages,\n\t\t\t\t\topts: invokeOpts,\n\t\t\t\t\tcontext: invokeOpts?.keyContext,\n\t\t\t\t};\n\t\t\t\tconst raw = await (keyFn as (c: LLMCacheKeyContext) => string | Promise<string>)(ctx);\n\t\t\t\treturn `${keyPrefix}:${raw}`;\n\t\t\t}\n\t\t\tconst raw = await (\n\t\t\t\tkeyFn as (m: readonly ChatMessage[], o?: LLMInvokeOptions) => string | Promise<string>\n\t\t\t)(messages, invokeOpts);\n\t\t\treturn `${keyPrefix}:${raw}`;\n\t\t}\n\t\treturn substrate.keyFor({ messages, opts: invokeOpts });\n\t}\n\n\treturn {\n\t\tkeyFor,\n\n\t\tasync lookup(messages, invokeOpts) {\n\t\t\tif (mode === \"write\") return undefined;\n\t\t\tif (keyFn) {\n\t\t\t\t// Custom keyFn path: we can't use substrate.lookup (it hashes\n\t\t\t\t// from its own keyContext). Build the key ourselves and load.\n\t\t\t\t// Strict-mode throw is the CALLER'S responsibility — we return\n\t\t\t\t// undefined on miss so callers can wrap the throw with their\n\t\t\t\t// domain-specific error type.\n\t\t\t\tconst key = await keyFor(messages, invokeOpts);\n\t\t\t\tconst raw = await storage.load(key);\n\t\t\t\tif (raw === undefined) return undefined;\n\t\t\t\treturn raw as V;\n\t\t\t}\n\t\t\treturn substrate.lookup({ messages, opts: invokeOpts });\n\t\t},\n\n\t\tasync store(messages, invokeOpts, value) {\n\t\t\tif (mode === \"read\") return;\n\t\t\tif (keyFn) {\n\t\t\t\tconst key = await keyFor(messages, invokeOpts);\n\t\t\t\tawait storage.save(key, value as unknown);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait substrate.store({ messages, opts: invokeOpts }, value);\n\t\t},\n\n\t\tasync forget(messages, invokeOpts) {\n\t\t\tif (mode === \"read\" || mode === \"write\") return;\n\t\t\tif (!storage.delete) return;\n\t\t\tif (keyFn) {\n\t\t\t\tconst key = await keyFor(messages, invokeOpts);\n\t\t\t\tawait storage.delete(key);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait substrate.forget({ messages, opts: invokeOpts });\n\t\t},\n\t};\n}\n","/**\n * Shared shell + shape-dispatch helpers for the LLM adapter layer.\n *\n * Wave A Unit 11 decision: the 9 middleware files and the observable adapter\n * all repeated the same three boilerplate patterns:\n *\n * 1. Building the returned `LLMAdapter` shell (provider/model/capabilities\n * pass-through). → `adapterWrapper(inner, {invoke, stream})`.\n * 2. Dispatching the adapter's `NodeInput<LLMResponse>` result across its\n * three possible shapes (Promise / Node / plain value) + a `recordedOnce`\n * double-record guard on the reactive path. → `adaptInvokeResult`.\n * 3. Constructing a `CallStatsEvent` from provider / model / tier / usage /\n * latency. → `buildCallStats`.\n *\n * Two small additions:\n * - `withLayer(adapter, layerName)` stamps a `meta.middlewareLayer` tag on\n * the returned adapter via a non-enumerable property, enabling\n * `describeAdapterStack(adapter)` to walk the wrap chain bottom-up.\n * - `describeAdapterStack(adapter)` returns the list of layer names from\n * innermost to outermost so users can inspect the resilient stack the same\n * way they inspect graph topology.\n */\n\nimport { ERROR, monotonicNs, type Node, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, onFirstData } from \"@graphrefly/pure-ts/extra\";\nimport type { CallStatsEvent } from \"../core/observable.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tNodeInput,\n\tStreamDelta,\n\tTokenUsage,\n} from \"../core/types.js\";\n\n// ---------------------------------------------------------------------------\n// adapterWrapper — LLMAdapter shell with provider/model/capabilities pass-through\n// ---------------------------------------------------------------------------\n\n/** Callable shape for the invoke / stream bodies that `adapterWrapper` composes. */\nexport type AdapterInvokeFn = (\n\tmessages: readonly ChatMessage[],\n\topts?: LLMInvokeOptions,\n) => NodeInput<LLMResponse>;\n\nexport type AdapterStreamFn = (\n\tmessages: readonly ChatMessage[],\n\topts?: LLMInvokeOptions,\n) => AsyncIterable<StreamDelta>;\n\n/**\n * Builds an `LLMAdapter` shell around the given `invoke` / `stream`\n * implementations. Pass-through fields — `provider`, `model`, `capabilities`\n * — come from `inner` unless the caller overrides (`override.provider` etc.).\n *\n * Middleware files used to repeat `provider: inner.provider, model: inner.model,\n * capabilities: inner.capabilities?.bind(inner)` verbatim; this helper\n * captures that once.\n *\n * @category internal\n */\nexport function adapterWrapper(\n\tinner: LLMAdapter,\n\timpl: { invoke: AdapterInvokeFn; stream: AdapterStreamFn },\n\toverride?: Partial<Pick<LLMAdapter, \"provider\" | \"model\" | \"capabilities\">>,\n): LLMAdapter {\n\treturn {\n\t\tprovider: override?.provider ?? inner.provider,\n\t\tmodel: override?.model ?? inner.model,\n\t\tcapabilities: override?.capabilities ?? inner.capabilities?.bind(inner),\n\t\tinvoke: impl.invoke,\n\t\tstream: impl.stream,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// adaptInvokeResult — shape-dispatch for NodeInput<LLMResponse>\n// ---------------------------------------------------------------------------\n\n/**\n * Shape-dispatch helper for `inner.invoke(...)` return values. Converts any of\n * the three `NodeInput<LLMResponse>` shapes (Promise, plain value, Node /\n * iterable) into the caller-requested output, applying `onResp` exactly once\n * on the first DATA emission.\n *\n * **Paths.**\n * - `Promise<LLMResponse>` → `Promise<R>` (chains `onResp` via `.then`; if\n * `onError` is provided, wires `.catch` so rejected Promises flow to the\n * error path just like the stream body does).\n * - Plain `LLMResponse` (object with `content` field) → `R` (calls `onResp`\n * synchronously and returns the mapped value).\n * - Anything else → reactive `Node<R>` via `fromAny` + `onFirstData(onResp)`\n * so late subscribers don't re-fire the side effect.\n *\n * @category internal\n */\nexport function adaptInvokeResult<R>(\n\tinput: NodeInput<LLMResponse>,\n\topts: {\n\t\tonResp: (resp: LLMResponse) => R;\n\t\t/**\n\t\t * If provided, rejected Promises are piped through this handler (for\n\t\t * stats / budget recording) before re-throwing. Signature mirrors the\n\t\t * stream try/catch shape so callers can share a single error-recording\n\t\t * closure across both paths.\n\t\t */\n\t\tonError?: (err: unknown) => void;\n\t\t/** Optional node name for the reactive-path derived (describe-friendly). */\n\t\tname?: string;\n\t},\n): Promise<R> | R | Node<R> {\n\tconst { onResp, onError, name } = opts;\n\n\t// Promise / thenable: chain .then, optionally .catch.\n\tif (input != null && typeof (input as PromiseLike<LLMResponse>).then === \"function\") {\n\t\tconst p = input as Promise<LLMResponse>;\n\t\tif (onError) {\n\t\t\treturn p.then(onResp).catch((err: unknown) => {\n\t\t\t\tonError(err);\n\t\t\t\tthrow err;\n\t\t\t});\n\t\t}\n\t\treturn p.then(onResp);\n\t}\n\t// Plain LLMResponse (synchronous).\n\tif (input != null && typeof input === \"object\" && \"content\" in (input as object)) {\n\t\treturn onResp(input as LLMResponse);\n\t}\n\t// Reactive / iterable — map inside a `derived` guarded by `onFirstData`\n\t// so the side-effect fires exactly once per node lifetime (push-on-\n\t// subscribe replay on late subscribers is silent).\n\tconst bridged = fromAny(input);\n\t// Wire `onError` via a side-subscription on the bridged node. `onFirstData`\n\t// only handles DATA — ERROR messages need their own hook so stats /\n\t// budget recording fires symmetrically with the Promise path. The\n\t// subscription runs for the lifetime of the derived below (keepalive via\n\t// the downstream derived's activation), and fires at most once per ERROR\n\t// frame. Without this, ERRORs on Node-shaped adapter returns silently\n\t// bypass budget/observable recording.\n\tif (onError) {\n\t\tlet errored = false;\n\t\tbridged.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (errored) return;\n\t\t\t\tif ((m as readonly [symbol, unknown])[0] === ERROR) {\n\t\t\t\t\terrored = true;\n\t\t\t\t\tonError((m as readonly [symbol, unknown])[1]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\t// `captured` holds the mapped value from the first DATA so re-subscribers\n\t// and re-emissions see a stable mapped value without re-firing `onResp`.\n\t// Use a distinct `mapped` sentinel (not nullish) because `onResp` may\n\t// legitimately return `null` / `undefined` / `0` — the prior\n\t// `captured ?? onResp(v)` guard re-fired `onResp` on falsy captured, which\n\t// broke the \"exactly once per node lifetime\" contract.\n\tlet captured: R;\n\tlet mapped = false;\n\tconst tapped = onFirstData(bridged, (v) => {\n\t\tcaptured = onResp(v);\n\t\tmapped = true;\n\t});\n\treturn node<R>(\n\t\t[tapped],\n\t\t(batchData, actions, ctx) => {\n\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t);\n\t\t\tconst v = data[0];\n\t\t\tif (v == null) {\n\t\t\t\tactions.emit(null as R);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (mapped) {\n\t\t\t\tactions.emit(captured);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tactions.emit(onResp(v as LLMResponse));\n\t\t},\n\t\t{ describeKind: \"derived\", name: name ?? \"adapt/invokeTap\" },\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// buildCallStats — CallStatsEvent constructor\n// ---------------------------------------------------------------------------\n\nexport interface BuildCallStatsArgs {\n\tprovider: string;\n\tmodel: string;\n\ttier?: string;\n\tusage: TokenUsage;\n\tstartNs: number;\n\tmethod: \"invoke\" | \"stream\";\n\terror?: { readonly type: string; readonly message: string };\n\t/** Override the wall-clock stamp (useful for tests / replay). */\n\tstartWallClockNs?: number;\n\t/** Override the monotonic end stamp (useful for tests). */\n\tendNs?: number;\n}\n\n/**\n * Constructs a {@link CallStatsEvent} from the arguments observable.ts and\n * budget-gate.ts used to assemble inline. The `timestamp` / `latencyMs` are\n * computed from `startNs` + (optional) `endNs`; `wallClock` is snapshot at\n * call-start via `wallClockNs()` unless overridden.\n *\n * @category internal\n */\nexport function buildCallStats(args: BuildCallStatsArgs): CallStatsEvent {\n\tconst end = args.endNs ?? monotonicNs();\n\treturn {\n\t\ttimestamp: end,\n\t\twallClock: args.startWallClockNs ?? wallClockNs(),\n\t\tprovider: args.provider,\n\t\tmodel: args.model,\n\t\ttier: args.tier,\n\t\tusage: args.usage,\n\t\tlatencyMs: Math.max(0, (end - args.startNs) / 1e6),\n\t\tmethod: args.method,\n\t\t...(args.error ? { error: args.error } : {}),\n\t};\n}\n\n/** Convenience — empty disaggregated usage stub used by every middleware. */\nexport function emptyUsageStub(): TokenUsage {\n\treturn { input: { regular: 0 }, output: { regular: 0 } };\n}\n\n// ---------------------------------------------------------------------------\n// meta.middlewareLayer + describeAdapterStack (Unit 11 Q1 user directive)\n// ---------------------------------------------------------------------------\n\n/** Symbol key carrying the wrap chain on the returned adapter. Non-enumerable. */\nconst MIDDLEWARE_LAYERS = Symbol.for(\"graphrefly.adapter.middlewareLayers\");\n\n/**\n * Stamp `adapter` with a middleware-layer name and return it. The stamp is a\n * non-enumerable property keyed by `Symbol.for(\"graphrefly.adapter.middlewareLayers\")`\n * — opaque to users, visible via {@link describeAdapterStack}.\n *\n * Each wrap prepends its layer to `inner`'s chain so the stack can be walked\n * bottom-up (innermost first). Providers have no layer stamp — they show up\n * as the bottom of the chain via their `provider` / `model` identity.\n *\n * @category internal\n */\nexport function withLayer<A extends LLMAdapter>(\n\tadapter: A,\n\tlayerName: string,\n\tinner?: LLMAdapter,\n): A {\n\tconst innerLayers = inner ? readLayers(inner) : [];\n\tconst chain = [...innerLayers, layerName];\n\tObject.defineProperty(adapter, MIDDLEWARE_LAYERS, {\n\t\tvalue: Object.freeze(chain),\n\t\tenumerable: false,\n\t\twritable: false,\n\t\tconfigurable: false,\n\t});\n\treturn adapter;\n}\n\n/**\n * Returns the middleware-layer names stamped on `adapter`, innermost first.\n * An adapter that has never been wrapped returns `[]` — callers combine the\n * result with `adapter.provider` / `adapter.model` for a full stack render.\n *\n * @example\n * ```ts\n * const stack = describeAdapterStack(resilientAdapter(anthropicAdapter(), opts).adapter);\n * // → [\"withLLMTimeout\", \"withRetry\", \"withLLMBreaker\", \"withBudgetGate\", \"withRateLimiter\", \"cascade\"]\n * ```\n *\n * @category extra\n */\nexport function describeAdapterStack(adapter: LLMAdapter): readonly string[] {\n\treturn readLayers(adapter);\n}\n\nfunction readLayers(adapter: LLMAdapter): readonly string[] {\n\tconst v = (adapter as unknown as Record<symbol, unknown>)[MIDDLEWARE_LAYERS];\n\treturn Array.isArray(v) ? (v as readonly string[]) : [];\n}\n","/**\n * GoogleAdapter — default fetch-backed, optional SDK-backed.\n *\n * The SDK-backed path targets the `@google/genai` SDK shape:\n * `client.models.generateContent({ model, contents, config })` — single\n * param, with generation params and `abortSignal` under `config`. The\n * legacy `@google/generative-ai` two-arg `(params, {signal})` shape is no\n * longer accepted; pass a `GoogleGenAI` instance via `opts.sdk`.\n *\n * Maps Gemini `usageMetadata`:\n * - `promptTokenCount` minus `cachedContentTokenCount` → `input.regular`\n * - `cachedContentTokenCount` → `input.cacheRead`\n * - `candidatesTokenCount` → `output.regular`\n * - `thoughtsTokenCount` → `output.reasoning`\n * - `toolUsePromptTokenCount` → `input.toolUse`\n * - `promptTokensDetails[]` → `input.{image,audio,video}` per modality\n */\n\nimport { monotonicNs } from \"@graphrefly/pure-ts/core\";\nimport { makeHttpError } from \"../../../../base/io/http-error.js\";\nimport { parseSSEStream } from \"../../../../base/io/sse.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n\tTokenUsage,\n\tToolDefinition,\n} from \"../core/types.js\";\n\nexport interface GoogleAdapterOptions {\n\t/** API key. Falls back to `process.env.GOOGLE_API_KEY` / `GEMINI_API_KEY` on Node. */\n\tapiKey?: string;\n\tmodel?: string;\n\tbaseURL?: string;\n\t/** Extra headers on every request. */\n\theaders?: Record<string, string>;\n\t/**\n\t * Optional `@google/genai` SDK instance (e.g. `new GoogleGenAI({apiKey})`).\n\t * When omitted, the adapter uses the fetch-backed path against the\n\t * Generative Language REST API.\n\t */\n\tsdk?: GoogleSdkLike;\n\tfetchImpl?: typeof fetch;\n}\n\n/**\n * Duck-type matching the `@google/genai` (`GoogleGenAI`) SDK shape:\n * single-param `generateContent({ model, contents, config })` where\n * generation parameters and `abortSignal` live under `config`.\n *\n * The `@google/generative-ai` predecessor's two-arg `(params, {signal})`\n * shape is no longer accepted.\n */\nexport interface GoogleSdkLike {\n\tmodels: {\n\t\tgenerateContent(params: GoogleSdkRequestParams): Promise<GeminiResponse>;\n\t\tgenerateContentStream?(\n\t\t\tparams: GoogleSdkRequestParams,\n\t\t): Promise<AsyncIterable<GeminiResponse>> | AsyncIterable<GeminiResponse>;\n\t};\n}\n\n/** Single-param request shape consumed by `@google/genai`'s `models.generateContent`. */\nexport interface GoogleSdkRequestParams {\n\tmodel: string;\n\tcontents: unknown;\n\tconfig?: GoogleSdkRequestConfig;\n}\n\n/**\n * Generation config under the new SDK. `abortSignal` is the cancellation\n * channel — there is no second-arg `{signal}`.\n */\nexport interface GoogleSdkRequestConfig {\n\tabortSignal?: AbortSignal;\n\ttemperature?: number;\n\tmaxOutputTokens?: number;\n\tsystemInstruction?: unknown;\n\ttools?: unknown;\n\tthinkingConfig?: unknown;\n\t[extra: string]: unknown;\n}\n\ninterface GeminiResponse {\n\tcandidates?: ReadonlyArray<{\n\t\tcontent?: {\n\t\t\trole?: string;\n\t\t\tparts?: ReadonlyArray<{\n\t\t\t\ttext?: string;\n\t\t\t\tthought?: boolean;\n\t\t\t\tfunctionCall?: { name: string; args: Record<string, unknown> };\n\t\t\t}>;\n\t\t};\n\t\tfinishReason?: string;\n\t}>;\n\tusageMetadata?: GeminiUsage;\n\tmodelVersion?: string;\n}\n\ninterface GeminiUsage {\n\tpromptTokenCount?: number;\n\tcandidatesTokenCount?: number;\n\ttotalTokenCount?: number;\n\tthoughtsTokenCount?: number;\n\tcachedContentTokenCount?: number;\n\ttoolUsePromptTokenCount?: number;\n\tpromptTokensDetails?: ReadonlyArray<{ modality: string; tokenCount: number }>;\n\tcandidatesTokensDetails?: ReadonlyArray<{ modality: string; tokenCount: number }>;\n\tcacheTokensDetails?: ReadonlyArray<{ modality: string; tokenCount: number }>;\n}\n\nexport function googleAdapter(opts: GoogleAdapterOptions = {}): LLMAdapter {\n\tif (opts.sdk) return sdkBackedGoogle(opts);\n\treturn fetchBackedGoogle(opts);\n}\n\n// ---------------------------------------------------------------------------\n// Mapping\n// ---------------------------------------------------------------------------\n\nfunction toGeminiRequest(\n\tmessages: readonly ChatMessage[],\n\tinvokeOpts: LLMInvokeOptions | undefined,\n): Record<string, unknown> {\n\tconst systemParts: string[] = [];\n\tconst contents: Array<{\n\t\trole: string;\n\t\tparts: Array<{ text?: string; functionCall?: unknown; functionResponse?: unknown }>;\n\t}> = [];\n\tif (invokeOpts?.systemPrompt) systemParts.push(invokeOpts.systemPrompt);\n\n\tfor (const m of messages) {\n\t\tif (m.role === \"system\") {\n\t\t\tsystemParts.push(m.content);\n\t\t\tcontinue;\n\t\t}\n\t\tif (m.role === \"tool\") {\n\t\t\tcontents.push({\n\t\t\t\trole: \"user\",\n\t\t\t\tparts: [\n\t\t\t\t\t{\n\t\t\t\t\t\tfunctionResponse: {\n\t\t\t\t\t\t\tname: m.name ?? m.toolCallId ?? \"tool\",\n\t\t\t\t\t\t\tresponse: { result: m.content },\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (m.role === \"assistant\" && m.toolCalls && m.toolCalls.length > 0) {\n\t\t\tconst parts: Array<{ text?: string; functionCall?: unknown }> = [];\n\t\t\tif (m.content) parts.push({ text: m.content });\n\t\t\tfor (const tc of m.toolCalls) {\n\t\t\t\tparts.push({ functionCall: { name: tc.name, args: tc.arguments } });\n\t\t\t}\n\t\t\tcontents.push({ role: \"model\", parts });\n\t\t\tcontinue;\n\t\t}\n\t\tcontents.push({\n\t\t\trole: m.role === \"assistant\" ? \"model\" : \"user\",\n\t\t\tparts: [{ text: m.content }],\n\t\t});\n\t}\n\n\tconst body: Record<string, unknown> = { contents };\n\tif (systemParts.length > 0) {\n\t\tbody.systemInstruction = { role: \"system\", parts: [{ text: systemParts.join(\"\\n\\n\") }] };\n\t}\n\tconst genConfig: Record<string, unknown> = {};\n\tif (invokeOpts?.maxTokens != null) genConfig.maxOutputTokens = invokeOpts.maxTokens;\n\tif (invokeOpts?.temperature != null) genConfig.temperature = invokeOpts.temperature;\n\tif (invokeOpts?.maxReasoningTokens != null) {\n\t\tgenConfig.thinkingConfig = { thinkingBudget: invokeOpts.maxReasoningTokens };\n\t}\n\tif (Object.keys(genConfig).length > 0) body.generationConfig = genConfig;\n\tif (invokeOpts?.tools && invokeOpts.tools.length > 0) {\n\t\tbody.tools = [{ functionDeclarations: invokeOpts.tools.map(toGeminiTool) }];\n\t}\n\tif (invokeOpts?.providerExtras) Object.assign(body, invokeOpts.providerExtras);\n\treturn body;\n}\n\nfunction toGeminiTool(t: ToolDefinition): Record<string, unknown> {\n\treturn {\n\t\tname: t.name,\n\t\tdescription: t.description,\n\t\tparameters: t.parameters,\n\t};\n}\n\n/**\n * Reshape the fetch-API request body into the SDK's `{ model, contents,\n * config }` form. Generation params (`temperature`, `maxOutputTokens`,\n * `thinkingConfig`) move from `body.generationConfig.*` to `config.*`;\n * `systemInstruction` and `tools` move from top-level body keys into\n * `config`; `abortSignal` is threaded into `config`. `providerExtras` keys\n * spread into `config` so escape-hatch usage remains identical.\n */\nfunction toSdkParams(\n\tbody: Record<string, unknown>,\n\tmodel: string,\n\tsignal: AbortSignal | undefined,\n): GoogleSdkRequestParams {\n\tconst config: GoogleSdkRequestConfig = {};\n\tconst gen = body.generationConfig as Record<string, unknown> | undefined;\n\tif (gen) {\n\t\tif (typeof gen.maxOutputTokens === \"number\") config.maxOutputTokens = gen.maxOutputTokens;\n\t\tif (typeof gen.temperature === \"number\") config.temperature = gen.temperature;\n\t\tif (gen.thinkingConfig) config.thinkingConfig = gen.thinkingConfig;\n\t}\n\tif (body.systemInstruction) config.systemInstruction = body.systemInstruction;\n\tif (body.tools) config.tools = body.tools;\n\tfor (const [k, v] of Object.entries(body)) {\n\t\tif (\n\t\t\tk === \"contents\" ||\n\t\t\tk === \"generationConfig\" ||\n\t\t\tk === \"systemInstruction\" ||\n\t\t\tk === \"tools\" ||\n\t\t\t// Skip `abortSignal` so a caller-supplied entry in `providerExtras`\n\t\t\t// can't briefly land in `config.abortSignal` before being\n\t\t\t// overwritten — the canonical signal channel is the second\n\t\t\t// `signal` argument (set on `config.abortSignal` below).\n\t\t\tk === \"abortSignal\" ||\n\t\t\t// Skip `model` so a stray `body.model` (not produced by\n\t\t\t// `toGeminiRequest` today, but defensively guarded) doesn't\n\t\t\t// duplicate the top-level `model` field on the SDK request.\n\t\t\tk === \"model\"\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\t\tconfig[k] = v;\n\t}\n\tif (signal) config.abortSignal = signal;\n\treturn {\n\t\tmodel,\n\t\tcontents: body.contents,\n\t\tconfig: Object.keys(config).length > 0 ? config : undefined,\n\t};\n}\n\nfunction mapUsage(u: GeminiUsage | undefined): TokenUsage {\n\tconst usage: TokenUsage = {\n\t\tinput: { regular: 0 },\n\t\toutput: { regular: 0 },\n\t\traw: u,\n\t};\n\tif (!u) return usage;\n\tconst promptTotal = u.promptTokenCount ?? 0;\n\tconst cached = u.cachedContentTokenCount ?? 0;\n\tusage.input.regular = Math.max(0, promptTotal - cached);\n\tif (cached > 0) usage.input.cacheRead = cached;\n\tif (u.toolUsePromptTokenCount) usage.input.toolUse = u.toolUsePromptTokenCount;\n\tif (u.promptTokensDetails) {\n\t\tfor (const d of u.promptTokensDetails) {\n\t\t\tconst modality = d.modality?.toLowerCase();\n\t\t\tif (modality === \"image\") usage.input.image = (usage.input.image ?? 0) + d.tokenCount;\n\t\t\telse if (modality === \"audio\") usage.input.audio = (usage.input.audio ?? 0) + d.tokenCount;\n\t\t\telse if (modality === \"video\") usage.input.video = (usage.input.video ?? 0) + d.tokenCount;\n\t\t}\n\t}\n\tusage.output.regular = u.candidatesTokenCount ?? 0;\n\tif (u.thoughtsTokenCount) usage.output.reasoning = u.thoughtsTokenCount;\n\treturn usage;\n}\n\nfunction toLLMResponse(json: GeminiResponse, latencyMs: number): LLMResponse {\n\tconst cand = json.candidates?.[0];\n\tconst parts = cand?.content?.parts ?? [];\n\tconst textParts: string[] = [];\n\tconst toolCalls: { id: string; name: string; arguments: Record<string, unknown> }[] = [];\n\tlet i = 0;\n\tfor (const p of parts) {\n\t\tif (typeof p.text === \"string\") textParts.push(p.text);\n\t\tif (p.functionCall) {\n\t\t\ttoolCalls.push({\n\t\t\t\tid: `${p.functionCall.name}-${i++}`,\n\t\t\t\tname: p.functionCall.name,\n\t\t\t\targuments: p.functionCall.args ?? {},\n\t\t\t});\n\t\t}\n\t}\n\treturn {\n\t\tcontent: textParts.join(\"\"),\n\t\ttoolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n\t\tusage: mapUsage(json.usageMetadata),\n\t\tfinishReason: cand?.finishReason,\n\t\tlatencyMs,\n\t\tmodel: json.modelVersion,\n\t\tprovider: \"google\",\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Fetch-backed\n// ---------------------------------------------------------------------------\n\nfunction resolveApiKey(opts: GoogleAdapterOptions): string | undefined {\n\tif (opts.apiKey) return opts.apiKey;\n\tconst env = (globalThis as { process?: { env?: Record<string, string> } }).process?.env;\n\treturn env?.GOOGLE_API_KEY ?? env?.GEMINI_API_KEY;\n}\n\nfunction fetchBackedGoogle(opts: GoogleAdapterOptions): LLMAdapter {\n\tconst baseURL = opts.baseURL ?? \"https://generativelanguage.googleapis.com/v1beta\";\n\tconst fetchImpl = opts.fetchImpl ?? fetch;\n\n\tconst pickModel = (invokeOpts: LLMInvokeOptions | undefined): string => {\n\t\tconst model = invokeOpts?.model ?? opts.model;\n\t\tif (!model)\n\t\t\tthrow new Error(\"googleAdapter: model must be set via options.model or invokeOpts.model\");\n\t\treturn model;\n\t};\n\n\tconst keyParam = (): string => {\n\t\tconst key = resolveApiKey(opts);\n\t\tif (!key) throw new Error(\"googleAdapter: apiKey required for invoke/stream\");\n\t\treturn `key=${encodeURIComponent(key)}`;\n\t};\n\n\treturn {\n\t\tprovider: \"google\",\n\t\tmodel: opts.model,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst model = pickModel(invokeOpts);\n\t\t\tconst body = toGeminiRequest(messages, invokeOpts);\n\t\t\tconst start = monotonicNs();\n\t\t\tconst url = `${baseURL}/models/${encodeURIComponent(model)}:generateContent?${keyParam()}`;\n\t\t\tconst resp = await fetchImpl(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"content-type\": \"application/json\", ...(opts.headers ?? {}) },\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t});\n\t\t\tif (!resp.ok) throw await makeHttpError(resp, \"Google\");\n\t\t\tconst json = (await resp.json()) as GeminiResponse;\n\t\t\tconst latencyMs = Math.max(0, (monotonicNs() - start) / 1e6);\n\t\t\treturn toLLMResponse(json, latencyMs);\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst model = pickModel(invokeOpts);\n\t\t\tconst body = toGeminiRequest(messages, invokeOpts);\n\t\t\tconst url = `${baseURL}/models/${encodeURIComponent(model)}:streamGenerateContent?alt=sse&${keyParam()}`;\n\t\t\tconst resp = await fetchImpl(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t\taccept: \"text/event-stream\",\n\t\t\t\t\t...(opts.headers ?? {}),\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t});\n\t\t\tif (!resp.ok) throw await makeHttpError(resp, \"Google\");\n\t\t\tif (!resp.body) throw new Error(\"googleAdapter: streaming response has no body\");\n\n\t\t\tlet finalUsage: GeminiUsage | undefined;\n\t\t\tlet finishReason: string | undefined;\n\n\t\t\tfor await (const event of parseSSEStream(resp.body, { signal: invokeOpts?.signal })) {\n\t\t\t\tif (!event.data) continue;\n\t\t\t\tlet parsed: GeminiResponse;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = JSON.parse(event.data) as GeminiResponse;\n\t\t\t\t} catch {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst cand = parsed.candidates?.[0];\n\t\t\t\tfor (const p of cand?.content?.parts ?? []) {\n\t\t\t\t\tif (typeof p.text === \"string\") {\n\t\t\t\t\t\tif (p.thought) yield { type: \"thinking\", delta: p.text };\n\t\t\t\t\t\telse yield { type: \"token\", delta: p.text };\n\t\t\t\t\t}\n\t\t\t\t\tif (p.functionCall) {\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"tool-call-delta\",\n\t\t\t\t\t\t\tdelta: {\n\t\t\t\t\t\t\t\tname: p.functionCall.name,\n\t\t\t\t\t\t\t\targumentsDelta: JSON.stringify(p.functionCall.args ?? {}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (cand?.finishReason) finishReason = cand.finishReason;\n\t\t\t\tif (parsed.usageMetadata) finalUsage = parsed.usageMetadata;\n\t\t\t}\n\t\t\tif (finalUsage) yield { type: \"usage\", usage: mapUsage(finalUsage) };\n\t\t\tyield { type: \"finish\", reason: finishReason ?? \"stop\" };\n\t\t},\n\t};\n}\n\nfunction sdkBackedGoogle(opts: GoogleAdapterOptions): LLMAdapter {\n\tconst sdk = opts.sdk;\n\tif (!sdk) throw new Error(\"sdkBackedGoogle: sdk instance required\");\n\n\treturn {\n\t\tprovider: \"google\",\n\t\tmodel: opts.model,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst body = toGeminiRequest(messages, invokeOpts);\n\t\t\tconst model = invokeOpts?.model ?? opts.model;\n\t\t\tif (!model) throw new Error(\"googleAdapter: model required\");\n\t\t\tconst params = toSdkParams(body, model, invokeOpts?.signal);\n\t\t\tconst start = monotonicNs();\n\t\t\tconst resp = await sdk.models.generateContent(params);\n\t\t\tconst latencyMs = Math.max(0, (monotonicNs() - start) / 1e6);\n\t\t\treturn toLLMResponse(resp, latencyMs);\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tif (!sdk.models.generateContentStream) {\n\t\t\t\tthrow new Error(\"sdkBackedGoogle: SDK instance does not expose generateContentStream\");\n\t\t\t}\n\t\t\tconst body = toGeminiRequest(messages, invokeOpts);\n\t\t\tconst model = invokeOpts?.model ?? opts.model;\n\t\t\tif (!model) throw new Error(\"googleAdapter: model required\");\n\t\t\tconst params = toSdkParams(body, model, invokeOpts?.signal);\n\t\t\tlet finalUsage: GeminiUsage | undefined;\n\t\t\tlet finishReason: string | undefined;\n\t\t\t// `@google/genai` returns `Promise<AsyncIterable<...>>`; older shapes\n\t\t\t// returned the iterable directly. Awaiting a non-thenable resolves\n\t\t\t// to itself, so this works for both.\n\t\t\tconst stream = await sdk.models.generateContentStream(params);\n\t\t\tfor await (const chunk of stream) {\n\t\t\t\tconst cand = chunk.candidates?.[0];\n\t\t\t\tfor (const p of cand?.content?.parts ?? []) {\n\t\t\t\t\tif (typeof p.text === \"string\") {\n\t\t\t\t\t\tif (p.thought) yield { type: \"thinking\", delta: p.text };\n\t\t\t\t\t\telse yield { type: \"token\", delta: p.text };\n\t\t\t\t\t}\n\t\t\t\t\tif (p.functionCall) {\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: \"tool-call-delta\",\n\t\t\t\t\t\t\tdelta: {\n\t\t\t\t\t\t\t\tname: p.functionCall.name,\n\t\t\t\t\t\t\t\targumentsDelta: JSON.stringify(p.functionCall.args ?? {}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (cand?.finishReason) finishReason = cand.finishReason;\n\t\t\t\tif (chunk.usageMetadata) finalUsage = chunk.usageMetadata;\n\t\t\t}\n\t\t\tif (finalUsage) yield { type: \"usage\", usage: mapUsage(finalUsage) };\n\t\t\tyield { type: \"finish\", reason: finishReason ?? \"stop\" };\n\t\t},\n\t};\n}\n","/**\n * OpenAICompatAdapter — default fetch-backed, optional SDK-backed.\n *\n * Covers any provider that speaks OpenAI chat/completions. Preset base URLs\n * for OpenAI, OpenRouter, Groq, Ollama, DeepSeek, xAI Grok (all expose the\n * same `/v1/chat/completions` shape).\n *\n * Token usage mapping:\n * - `prompt_tokens` → `input.regular` (minus cached_tokens)\n * - `prompt_tokens_details.cached_tokens` → `input.cacheRead`\n * - `prompt_tokens_details.audio_tokens` → `input.audio`\n * - `completion_tokens` → `output.regular` (minus reasoning)\n * - `completion_tokens_details.reasoning_tokens` → `output.reasoning`\n * - `completion_tokens_details.audio_tokens` → `output.audio`\n * - `completion_tokens_details.accepted_prediction_tokens` → `output.predictionAccepted`\n * - `completion_tokens_details.rejected_prediction_tokens` → `output.predictionRejected`\n *\n * DeepSeek compatibility: `prompt_cache_hit_tokens` / `prompt_cache_miss_tokens`\n * are surfaced in the `raw` field of `TokenUsage`; when present we prefer\n * them over the OpenAI-style `cached_tokens` for cache-read attribution.\n */\n\nimport { monotonicNs } from \"@graphrefly/pure-ts/core\";\nimport { makeHttpError } from \"../../../../base/io/http-error.js\";\nimport { parseSSEStream } from \"../../../../base/io/sse.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n\tTokenUsage,\n\tToolDefinition,\n} from \"../core/types.js\";\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport type OpenAICompatPreset = \"openai\" | \"openrouter\" | \"groq\" | \"ollama\" | \"deepseek\" | \"xai\";\n\nconst PRESETS: Record<\n\tOpenAICompatPreset,\n\t{ baseURL: string; apiKeyEnv?: string; provider: string }\n> = {\n\topenai: { baseURL: \"https://api.openai.com/v1\", apiKeyEnv: \"OPENAI_API_KEY\", provider: \"openai\" },\n\topenrouter: {\n\t\tbaseURL: \"https://openrouter.ai/api/v1\",\n\t\tapiKeyEnv: \"OPENROUTER_API_KEY\",\n\t\tprovider: \"openrouter\",\n\t},\n\tgroq: { baseURL: \"https://api.groq.com/openai/v1\", apiKeyEnv: \"GROQ_API_KEY\", provider: \"groq\" },\n\tollama: { baseURL: \"http://localhost:11434/v1\", provider: \"ollama\" },\n\tdeepseek: {\n\t\tbaseURL: \"https://api.deepseek.com/v1\",\n\t\tapiKeyEnv: \"DEEPSEEK_API_KEY\",\n\t\tprovider: \"deepseek\",\n\t},\n\txai: { baseURL: \"https://api.x.ai/v1\", apiKeyEnv: \"XAI_API_KEY\", provider: \"xai\" },\n};\n\nexport interface OpenAICompatAdapterOptions {\n\tpreset?: OpenAICompatPreset;\n\t/** Explicit provider label (defaults to preset's provider). */\n\tprovider?: string;\n\t/** API key. Falls back to the preset's default env var on Node. */\n\tapiKey?: string;\n\tmodel?: string;\n\t/** Override base URL (wins over `preset`). */\n\tbaseURL?: string;\n\t/** Extra request headers. */\n\theaders?: Record<string, string>;\n\t/** Extra request-body fields merged on every request (OpenRouter routing etc.). */\n\tbodyExtras?: Record<string, unknown>;\n\t/** User-provided SDK instance (OpenAI-family shape). */\n\tsdk?: OpenAISdkLike;\n\t/** Custom fetch (for tests). */\n\tfetchImpl?: typeof fetch;\n}\n\nexport interface OpenAISdkLike {\n\tchat: {\n\t\tcompletions: {\n\t\t\tcreate(\n\t\t\t\tparams: Record<string, unknown>,\n\t\t\t\topts?: { signal?: AbortSignal },\n\t\t\t): Promise<OpenAIChatResponse>;\n\t\t};\n\t};\n}\n\ninterface OpenAIChatResponse {\n\tid: string;\n\tchoices: ReadonlyArray<{\n\t\tmessage: {\n\t\t\trole: string;\n\t\t\tcontent?: string | null;\n\t\t\ttool_calls?: ReadonlyArray<{\n\t\t\t\tid: string;\n\t\t\t\ttype: \"function\";\n\t\t\t\tfunction: { name: string; arguments: string };\n\t\t\t}>;\n\t\t\treasoning_content?: string;\n\t\t};\n\t\tfinish_reason?: string;\n\t}>;\n\tusage?: OpenAIUsage;\n\tmodel?: string;\n}\n\ninterface OpenAIUsage {\n\tprompt_tokens?: number;\n\tcompletion_tokens?: number;\n\ttotal_tokens?: number;\n\tprompt_tokens_details?: {\n\t\tcached_tokens?: number;\n\t\taudio_tokens?: number;\n\t};\n\tcompletion_tokens_details?: {\n\t\treasoning_tokens?: number;\n\t\taudio_tokens?: number;\n\t\taccepted_prediction_tokens?: number;\n\t\trejected_prediction_tokens?: number;\n\t};\n\t// DeepSeek\n\tprompt_cache_hit_tokens?: number;\n\tprompt_cache_miss_tokens?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function openAICompatAdapter(opts: OpenAICompatAdapterOptions = {}): LLMAdapter {\n\tif (opts.sdk) return sdkBackedOpenAI(opts);\n\treturn fetchBackedOpenAI(opts);\n}\n\n// ---------------------------------------------------------------------------\n// Mapping\n// ---------------------------------------------------------------------------\n\nfunction toOpenAIRequest(\n\tmessages: readonly ChatMessage[],\n\tinvokeOpts: LLMInvokeOptions | undefined,\n\tdefaultModel: string | undefined,\n\tstream: boolean,\n\tbodyExtras: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n\tconst model = invokeOpts?.model ?? defaultModel;\n\tif (!model)\n\t\tthrow new Error(\"openAICompatAdapter: model must be set via options.model or invokeOpts.model\");\n\tconst mapped = messages.map(toOpenAIMessage);\n\tif (invokeOpts?.systemPrompt && !messages.some((m) => m.role === \"system\")) {\n\t\tmapped.unshift({ role: \"system\", content: invokeOpts.systemPrompt });\n\t}\n\tconst body: Record<string, unknown> = { model, messages: mapped };\n\tif (invokeOpts?.maxTokens != null) body.max_tokens = invokeOpts.maxTokens;\n\tif (invokeOpts?.temperature != null) body.temperature = invokeOpts.temperature;\n\tif (invokeOpts?.tools && invokeOpts.tools.length > 0) {\n\t\tbody.tools = invokeOpts.tools.map(toOpenAITool);\n\t}\n\tif (invokeOpts?.maxReasoningTokens != null) {\n\t\tbody.reasoning = { max_tokens: invokeOpts.maxReasoningTokens };\n\t}\n\tif (stream) {\n\t\tbody.stream = true;\n\t\tbody.stream_options = { include_usage: true };\n\t}\n\tif (bodyExtras) Object.assign(body, bodyExtras);\n\tif (invokeOpts?.providerExtras) Object.assign(body, invokeOpts.providerExtras);\n\treturn body;\n}\n\nfunction toOpenAIMessage(m: ChatMessage): Record<string, unknown> {\n\tif (m.role === \"tool\") {\n\t\treturn { role: \"tool\", tool_call_id: m.toolCallId, content: m.content };\n\t}\n\tif (m.role === \"assistant\" && m.toolCalls && m.toolCalls.length > 0) {\n\t\treturn {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: m.content || null,\n\t\t\ttool_calls: m.toolCalls.map((tc) => ({\n\t\t\t\tid: tc.id,\n\t\t\t\ttype: \"function\",\n\t\t\t\tfunction: { name: tc.name, arguments: JSON.stringify(tc.arguments) },\n\t\t\t})),\n\t\t};\n\t}\n\treturn { role: m.role, content: m.content };\n}\n\nfunction toOpenAITool(t: ToolDefinition): Record<string, unknown> {\n\treturn {\n\t\ttype: \"function\",\n\t\tfunction: {\n\t\t\tname: t.name,\n\t\t\tdescription: t.description,\n\t\t\tparameters: t.parameters,\n\t\t},\n\t};\n}\n\nfunction mapUsage(u: OpenAIUsage | undefined): TokenUsage {\n\tconst usage: TokenUsage = {\n\t\tinput: { regular: 0 },\n\t\toutput: { regular: 0 },\n\t\traw: u,\n\t};\n\tif (!u) return usage;\n\tconst inputTotal = u.prompt_tokens ?? 0;\n\tlet cacheRead = u.prompt_tokens_details?.cached_tokens ?? 0;\n\tif (u.prompt_cache_hit_tokens != null) {\n\t\t// DeepSeek: prefer explicit hit/miss split when present\n\t\tcacheRead = u.prompt_cache_hit_tokens;\n\t\tusage.input.regular = u.prompt_cache_miss_tokens ?? Math.max(0, inputTotal - cacheRead);\n\t} else {\n\t\tusage.input.regular = Math.max(0, inputTotal - cacheRead);\n\t}\n\tif (cacheRead > 0) usage.input.cacheRead = cacheRead;\n\tif (u.prompt_tokens_details?.audio_tokens)\n\t\tusage.input.audio = u.prompt_tokens_details.audio_tokens;\n\n\tconst outputTotal = u.completion_tokens ?? 0;\n\tconst reasoning = u.completion_tokens_details?.reasoning_tokens ?? 0;\n\tusage.output.regular = Math.max(0, outputTotal - reasoning);\n\tif (reasoning > 0) usage.output.reasoning = reasoning;\n\tif (u.completion_tokens_details?.audio_tokens)\n\t\tusage.output.audio = u.completion_tokens_details.audio_tokens;\n\tif (u.completion_tokens_details?.accepted_prediction_tokens) {\n\t\tusage.output.predictionAccepted = u.completion_tokens_details.accepted_prediction_tokens;\n\t}\n\tif (u.completion_tokens_details?.rejected_prediction_tokens) {\n\t\tusage.output.predictionRejected = u.completion_tokens_details.rejected_prediction_tokens;\n\t}\n\treturn usage;\n}\n\nfunction toLLMResponse(json: OpenAIChatResponse, latencyMs: number, provider: string): LLMResponse {\n\tconst choice = json.choices[0];\n\tconst msg = choice?.message;\n\tconst content = msg?.content ?? \"\";\n\tconst toolCalls = (msg?.tool_calls ?? []).map((tc) => ({\n\t\tid: tc.id,\n\t\tname: tc.function.name,\n\t\targuments: safeJsonParse(tc.function.arguments),\n\t}));\n\treturn {\n\t\tcontent,\n\t\ttoolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n\t\tusage: mapUsage(json.usage),\n\t\tfinishReason: choice?.finish_reason,\n\t\tlatencyMs,\n\t\tmodel: json.model,\n\t\tprovider,\n\t};\n}\n\nfunction safeJsonParse(s: string): Record<string, unknown> {\n\ttry {\n\t\tconst parsed = JSON.parse(s);\n\t\treturn typeof parsed === \"object\" && parsed != null\n\t\t\t? (parsed as Record<string, unknown>)\n\t\t\t: { _raw: s };\n\t} catch {\n\t\treturn { _raw: s };\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Fetch-backed\n// ---------------------------------------------------------------------------\n\nfunction resolveConfig(opts: OpenAICompatAdapterOptions): {\n\tprovider: string;\n\tbaseURL: string;\n\tapiKey: string | undefined;\n} {\n\tconst preset = opts.preset ?? \"openai\";\n\tconst base = PRESETS[preset];\n\tconst baseURL = opts.baseURL ?? base.baseURL;\n\tconst provider = opts.provider ?? base.provider;\n\tconst envKey = base.apiKeyEnv;\n\tconst apiKey =\n\t\topts.apiKey ??\n\t\t(envKey\n\t\t\t? (globalThis as { process?: { env?: Record<string, string> } }).process?.env?.[envKey]\n\t\t\t: undefined);\n\treturn { provider, baseURL, apiKey };\n}\n\nfunction fetchBackedOpenAI(opts: OpenAICompatAdapterOptions): LLMAdapter {\n\tconst { provider, baseURL, apiKey } = resolveConfig(opts);\n\tconst fetchImpl = opts.fetchImpl ?? fetch;\n\tconst needsKey = provider !== \"ollama\"; // Ollama local default: no key required.\n\n\tconst commonHeaders = (): Record<string, string> => {\n\t\tconst h: Record<string, string> = {\n\t\t\t\"content-type\": \"application/json\",\n\t\t\t...(opts.headers ?? {}),\n\t\t};\n\t\tif (needsKey) {\n\t\t\tif (!apiKey)\n\t\t\t\tthrow new Error(`openAICompatAdapter[${provider}]: apiKey required for invoke/stream`);\n\t\t\th.authorization = `Bearer ${apiKey}`;\n\t\t}\n\t\treturn h;\n\t};\n\n\treturn {\n\t\tprovider,\n\t\tmodel: opts.model,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst body = toOpenAIRequest(messages, invokeOpts, opts.model, false, opts.bodyExtras);\n\t\t\tconst start = monotonicNs();\n\t\t\tconst resp = await fetchImpl(`${baseURL}/chat/completions`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: commonHeaders(),\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t});\n\t\t\tif (!resp.ok) throw await makeHttpError(resp, provider);\n\t\t\tconst json = (await resp.json()) as OpenAIChatResponse;\n\t\t\tconst latencyMs = Math.max(0, (monotonicNs() - start) / 1e6);\n\t\t\treturn toLLMResponse(json, latencyMs, provider);\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst body = toOpenAIRequest(messages, invokeOpts, opts.model, true, opts.bodyExtras);\n\t\t\tconst resp = await fetchImpl(`${baseURL}/chat/completions`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { ...commonHeaders(), accept: \"text/event-stream\" },\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t});\n\t\t\tif (!resp.ok) throw await makeHttpError(resp, provider);\n\t\t\tif (!resp.body)\n\t\t\t\tthrow new Error(`openAICompatAdapter[${provider}]: streaming response has no body`);\n\n\t\t\tlet finalUsage: OpenAIUsage | undefined;\n\t\t\tlet finishReason: string | undefined;\n\n\t\t\tfor await (const event of parseSSEStream(resp.body, { signal: invokeOpts?.signal })) {\n\t\t\t\tif (!event.data || event.data === \"[DONE]\") continue;\n\t\t\t\tlet parsed: Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = JSON.parse(event.data) as Record<string, unknown>;\n\t\t\t\t} catch {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// Streaming shape: choices[0].delta.{content?, tool_calls?, reasoning_content?}\n\t\t\t\tconst choices = parsed.choices as\n\t\t\t\t\t| ReadonlyArray<{\n\t\t\t\t\t\t\tdelta?: {\n\t\t\t\t\t\t\t\tcontent?: string;\n\t\t\t\t\t\t\t\ttool_calls?: ReadonlyArray<{\n\t\t\t\t\t\t\t\t\tindex: number;\n\t\t\t\t\t\t\t\t\tid?: string;\n\t\t\t\t\t\t\t\t\tfunction?: { name?: string; arguments?: string };\n\t\t\t\t\t\t\t\t}>;\n\t\t\t\t\t\t\t\treasoning_content?: string;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tfinish_reason?: string;\n\t\t\t\t\t }>\n\t\t\t\t\t| undefined;\n\t\t\t\tif (choices) {\n\t\t\t\t\tconst c = choices[0];\n\t\t\t\t\tif (c?.delta?.content) yield { type: \"token\", delta: c.delta.content };\n\t\t\t\t\tif (c?.delta?.reasoning_content) {\n\t\t\t\t\t\tyield { type: \"thinking\", delta: c.delta.reasoning_content };\n\t\t\t\t\t}\n\t\t\t\t\tif (c?.delta?.tool_calls) {\n\t\t\t\t\t\tfor (const tc of c.delta.tool_calls) {\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: \"tool-call-delta\",\n\t\t\t\t\t\t\t\tdelta: {\n\t\t\t\t\t\t\t\t\tid: tc.id,\n\t\t\t\t\t\t\t\t\tname: tc.function?.name,\n\t\t\t\t\t\t\t\t\targumentsDelta: tc.function?.arguments,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (c?.finish_reason) finishReason = c.finish_reason;\n\t\t\t\t}\n\t\t\t\t// Yield every usage delta the provider emits (Anthropic, Groq, and\n\t\t\t\t// some OpenAI-compat providers can emit mid-stream usage). Downstream\n\t\t\t\t// consumers treat the most-recent delta as authoritative. See D5b in\n\t\t\t\t// adapter QA session.\n\t\t\t\tif (parsed.usage) {\n\t\t\t\t\tfinalUsage = parsed.usage as OpenAIUsage;\n\t\t\t\t\tyield { type: \"usage\", usage: mapUsage(finalUsage) };\n\t\t\t\t}\n\t\t\t}\n\t\t\tyield { type: \"finish\", reason: finishReason ?? \"stop\" };\n\t\t},\n\t};\n}\n\nfunction sdkBackedOpenAI(opts: OpenAICompatAdapterOptions): LLMAdapter {\n\tconst sdk = opts.sdk;\n\tif (!sdk) throw new Error(\"sdkBackedOpenAI: sdk instance required\");\n\tconst { provider } = resolveConfig(opts);\n\treturn {\n\t\tprovider,\n\t\tmodel: opts.model,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst body = toOpenAIRequest(messages, invokeOpts, opts.model, false, opts.bodyExtras);\n\t\t\tconst start = monotonicNs();\n\t\t\tconst resp = await sdk.chat.completions.create(body, { signal: invokeOpts?.signal });\n\t\t\tconst latencyMs = Math.max(0, (monotonicNs() - start) / 1e6);\n\t\t\treturn toLLMResponse(resp, latencyMs, provider);\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst body = toOpenAIRequest(messages, invokeOpts, opts.model, true, opts.bodyExtras);\n\t\t\tconst stream = (await sdk.chat.completions.create(body, {\n\t\t\t\tsignal: invokeOpts?.signal,\n\t\t\t})) as unknown as AsyncIterable<Record<string, unknown>>;\n\t\t\tlet finalUsage: OpenAIUsage | undefined;\n\t\t\tlet finishReason: string | undefined;\n\t\t\tfor await (const chunk of stream) {\n\t\t\t\tconst choices = (\n\t\t\t\t\tchunk as {\n\t\t\t\t\t\tchoices?: ReadonlyArray<{\n\t\t\t\t\t\t\tdelta?: {\n\t\t\t\t\t\t\t\tcontent?: string;\n\t\t\t\t\t\t\t\ttool_calls?: ReadonlyArray<{\n\t\t\t\t\t\t\t\t\tid?: string;\n\t\t\t\t\t\t\t\t\tfunction?: { name?: string; arguments?: string };\n\t\t\t\t\t\t\t\t}>;\n\t\t\t\t\t\t\t\treasoning_content?: string;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tfinish_reason?: string;\n\t\t\t\t\t\t}>;\n\t\t\t\t\t}\n\t\t\t\t).choices;\n\t\t\t\tif (choices) {\n\t\t\t\t\tconst c = choices[0];\n\t\t\t\t\tif (c?.delta?.content) yield { type: \"token\", delta: c.delta.content };\n\t\t\t\t\tif (c?.delta?.reasoning_content)\n\t\t\t\t\t\tyield { type: \"thinking\", delta: c.delta.reasoning_content };\n\t\t\t\t\tif (c?.delta?.tool_calls) {\n\t\t\t\t\t\tfor (const tc of c.delta.tool_calls) {\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: \"tool-call-delta\",\n\t\t\t\t\t\t\t\tdelta: {\n\t\t\t\t\t\t\t\t\tid: tc.id,\n\t\t\t\t\t\t\t\t\tname: tc.function?.name,\n\t\t\t\t\t\t\t\t\targumentsDelta: tc.function?.arguments,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (c?.finish_reason) finishReason = c.finish_reason;\n\t\t\t\t}\n\t\t\t\tconst u = (chunk as { usage?: OpenAIUsage }).usage;\n\t\t\t\tif (u) {\n\t\t\t\t\tfinalUsage = u;\n\t\t\t\t\tyield { type: \"usage\", usage: mapUsage(u) };\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!finalUsage) {\n\t\t\t\t// No usage emitted — yield nothing; downstream consumers default\n\t\t\t\t// to empty usage via their own fallback.\n\t\t\t}\n\t\t\tyield { type: \"finish\", reason: finishReason ?? \"stop\" };\n\t\t},\n\t};\n}\n","/**\n * `createAdapter` — provider-dispatching factory.\n *\n * One entry point, one config object. Picks the right concrete adapter by\n * `provider`, forwards everything else. Users who want finer control import\n * the concrete adapter directly (`anthropicAdapter`, `openAICompatAdapter`,\n * `googleAdapter`, `dryRunAdapter`, `webllmAdapter`, `chromeNanoAdapter`).\n */\n\nimport { type AnthropicAdapterOptions, anthropicAdapter } from \"../providers/anthropic.js\";\nimport { type DryRunAdapterOptions, dryRunAdapter } from \"../providers/dry-run.js\";\nimport { type FallbackAdapterOptions, fallbackAdapter } from \"../providers/fallback.js\";\nimport { type GoogleAdapterOptions, googleAdapter } from \"../providers/google.js\";\nimport {\n\ttype OpenAICompatAdapterOptions,\n\ttype OpenAICompatPreset,\n\topenAICompatAdapter,\n} from \"../providers/openai-compat.js\";\nimport type { LLMAdapter } from \"./types.js\";\n\nexport type AdapterProvider =\n\t| \"anthropic\"\n\t| OpenAICompatPreset // \"openai\" | \"openrouter\" | \"groq\" | \"ollama\" | \"deepseek\" | \"xai\"\n\t| \"google\"\n\t| \"dry-run\"\n\t| \"fallback\";\n\nexport interface CreateAdapterOptions {\n\tprovider: AdapterProvider;\n\tapiKey?: string;\n\tmodel?: string;\n\tbaseURL?: string;\n\theaders?: Record<string, string>;\n\t/** OpenAI-compat bodyExtras (OpenRouter routing, etc.). */\n\tbodyExtras?: Record<string, unknown>;\n\t/** Provider-specific SDK instance (any of AnthropicSdkLike / OpenAISdkLike / GoogleSdkLike). */\n\tsdk?: unknown;\n\t/** Custom fetch (for tests). */\n\tfetchImpl?: typeof fetch;\n\t/** Extra per-provider options forwarded verbatim. */\n\textras?: Record<string, unknown>;\n}\n\nexport function createAdapter(opts: CreateAdapterOptions): LLMAdapter {\n\tswitch (opts.provider) {\n\t\tcase \"anthropic\": {\n\t\t\tconst a: AnthropicAdapterOptions = {\n\t\t\t\tapiKey: opts.apiKey,\n\t\t\t\tmodel: opts.model,\n\t\t\t\tbaseURL: opts.baseURL,\n\t\t\t\theaders: opts.headers,\n\t\t\t\tsdk: opts.sdk as AnthropicAdapterOptions[\"sdk\"],\n\t\t\t\tfetchImpl: opts.fetchImpl,\n\t\t\t\t...(opts.extras as AnthropicAdapterOptions | undefined),\n\t\t\t};\n\t\t\treturn anthropicAdapter(a);\n\t\t}\n\t\tcase \"google\": {\n\t\t\tconst g: GoogleAdapterOptions = {\n\t\t\t\tapiKey: opts.apiKey,\n\t\t\t\tmodel: opts.model,\n\t\t\t\tbaseURL: opts.baseURL,\n\t\t\t\theaders: opts.headers,\n\t\t\t\tsdk: opts.sdk as GoogleAdapterOptions[\"sdk\"],\n\t\t\t\tfetchImpl: opts.fetchImpl,\n\t\t\t\t...(opts.extras as GoogleAdapterOptions | undefined),\n\t\t\t};\n\t\t\treturn googleAdapter(g);\n\t\t}\n\t\tcase \"dry-run\": {\n\t\t\tconst d: DryRunAdapterOptions = {\n\t\t\t\tmodel: opts.model,\n\t\t\t\t...(opts.extras as DryRunAdapterOptions | undefined),\n\t\t\t};\n\t\t\treturn dryRunAdapter(d);\n\t\t}\n\t\tcase \"fallback\": {\n\t\t\t// `provider`/`model` threaded as labels; `fixtures`/`record`/etc.\n\t\t\t// must come through `extras` since `CreateAdapterOptions` doesn't\n\t\t\t// have dedicated slots for them.\n\t\t\tconst f: FallbackAdapterOptions = {\n\t\t\t\tprovider: opts.provider,\n\t\t\t\tmodel: opts.model,\n\t\t\t\t...(opts.extras as FallbackAdapterOptions | undefined),\n\t\t\t};\n\t\t\treturn fallbackAdapter(f);\n\t\t}\n\t\t// OpenAI-compat presets\n\t\tcase \"openai\":\n\t\tcase \"openrouter\":\n\t\tcase \"groq\":\n\t\tcase \"ollama\":\n\t\tcase \"deepseek\":\n\t\tcase \"xai\": {\n\t\t\tconst c: OpenAICompatAdapterOptions = {\n\t\t\t\tpreset: opts.provider,\n\t\t\t\tapiKey: opts.apiKey,\n\t\t\t\tmodel: opts.model,\n\t\t\t\tbaseURL: opts.baseURL,\n\t\t\t\theaders: opts.headers,\n\t\t\t\tbodyExtras: opts.bodyExtras,\n\t\t\t\tsdk: opts.sdk as OpenAICompatAdapterOptions[\"sdk\"],\n\t\t\t\tfetchImpl: opts.fetchImpl,\n\t\t\t\t...(opts.extras as OpenAICompatAdapterOptions | undefined),\n\t\t\t};\n\t\t\treturn openAICompatAdapter(c);\n\t\t}\n\t\tdefault: {\n\t\t\tconst never: never = opts.provider;\n\t\t\tthrow new Error(`createAdapter: unknown provider: ${String(never)}`);\n\t\t}\n\t}\n}\n","/**\n * `cascadingLlmAdapter` — N-tier fallback over any mix of LLM adapters.\n *\n * Same structural pattern as `cascadingCache` and `Graph.attachSnapshotStorage`:\n * ordered list, first-success wins, per-tier breaker optional, filter gates\n * per request. Semantics:\n *\n * - `invoke()`: try tier 0 first. On error (or breaker-open), fall through\n * to tier 1, 2, ... until one succeeds or all fail.\n * - `stream()`: tries to start the stream on tier 0; once tokens begin, it\n * commits — failures in mid-stream surface rather than re-starting on the\n * next tier (would double-bill and confuse consumers). **State-machine\n * consumers (usage accounting, UI accumulators) must handle errors in a\n * catch block — no synthetic `{type: \"finish\"}` is emitted after a thrown\n * stream error.**\n * - `filter`: skips a tier for requests that use features it doesn't\n * support (e.g., Chrome Nano can't do tool use).\n * - `breaker`: per-tier circuit; when open, cascade treats the tier as\n * unavailable and moves on immediately.\n *\n * On exhaustion, throws `AllTiersExhaustedError` with separate `skipped` and\n * `failed` collections so consumers can distinguish \"no tier applicable\"\n * from \"all tiers failed\".\n */\n\nimport { fromAny } from \"@graphrefly/pure-ts/extra\";\nimport { firstValueFrom } from \"../../../../base/sources/settled.js\";\nimport {\n\ttype CircuitBreaker,\n\ttype CircuitBreakerOptions,\n\tcircuitBreaker,\n} from \"../../../../utils/resilience/index.js\";\nimport { withLayer } from \"../_internal/wrappers.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n} from \"../core/types.js\";\n\nexport interface AdapterTier {\n\tname: string;\n\tadapter: LLMAdapter;\n\t/** Per-tier circuit breaker. If omitted, no breaker on this tier. */\n\tbreaker?: CircuitBreakerOptions | CircuitBreaker;\n\t/** Skip this tier when the request doesn't fit (e.g. Chrome Nano + tools). */\n\tfilter?: (messages: readonly ChatMessage[], opts?: LLMInvokeOptions) => boolean;\n}\n\nexport interface CascadeExhaustionReport {\n\t/** Tiers that never ran (filter returned false, or breaker was open). */\n\treadonly skipped: ReadonlyArray<{ name: string; reason: \"filter\" | \"breaker\" }>;\n\t/** Tiers that ran and threw. */\n\treadonly failed: ReadonlyMap<string, unknown>;\n}\n\nexport interface CascadingLlmAdapterOptions {\n\tonFallback?: (from: string, to: string, error: unknown) => void;\n\tonExhausted?: (report: CascadeExhaustionReport) => void;\n\t/** Whether to attempt stream retry on subsequent tiers before first chunk. Default true. */\n\tstreamRetryBeforeFirstChunk?: boolean;\n}\n\ninterface ResolvedTier {\n\tname: string;\n\tadapter: LLMAdapter;\n\tbreaker?: CircuitBreaker;\n\tfilter?: (messages: readonly ChatMessage[], opts?: LLMInvokeOptions) => boolean;\n}\n\nexport class AllTiersExhaustedError extends Error {\n\toverride name = \"AllTiersExhaustedError\";\n\treadonly skipped: ReadonlyArray<{ name: string; reason: \"filter\" | \"breaker\" }>;\n\treadonly failed: ReadonlyMap<string, unknown>;\n\tconstructor(report: CascadeExhaustionReport) {\n\t\tconst parts: string[] = [];\n\t\tif (report.failed.size > 0) parts.push(`failed=[${[...report.failed.keys()].join(\",\")}]`);\n\t\tif (report.skipped.length > 0) {\n\t\t\tparts.push(`skipped=[${report.skipped.map((s) => `${s.name}(${s.reason})`).join(\",\")}]`);\n\t\t}\n\t\tsuper(`All LLM adapter tiers exhausted: ${parts.join(\" \")}`);\n\t\tthis.skipped = report.skipped;\n\t\tthis.failed = report.failed;\n\t}\n}\n\nexport function cascadingLlmAdapter(\n\ttiers: readonly AdapterTier[],\n\topts: CascadingLlmAdapterOptions = {},\n): LLMAdapter {\n\tif (tiers.length === 0) throw new RangeError(\"cascadingLlmAdapter: tiers must be non-empty\");\n\n\tconst resolved: ResolvedTier[] = tiers.map((t) => ({\n\t\tname: t.name,\n\t\tadapter: t.adapter,\n\t\tfilter: t.filter,\n\t\tbreaker: t.breaker\n\t\t\t? \"canExecute\" in t.breaker\n\t\t\t\t? (t.breaker as CircuitBreaker)\n\t\t\t\t: circuitBreaker(t.breaker as CircuitBreakerOptions)\n\t\t\t: undefined,\n\t}));\n\n\tconst streamRetryBeforeFirstChunk = opts.streamRetryBeforeFirstChunk ?? true;\n\n\tconst cascade: LLMAdapter = {\n\t\tprovider: \"cascading\",\n\t\tmodel: undefined,\n\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst skipped: Array<{ name: string; reason: \"filter\" | \"breaker\" }> = [];\n\t\t\tconst failed = new Map<string, unknown>();\n\t\t\tfor (let i = 0; i < resolved.length; i++) {\n\t\t\t\tconst t = resolved[i];\n\t\t\t\tif (t.filter && !t.filter(messages, invokeOpts)) {\n\t\t\t\t\tskipped.push({ name: t.name, reason: \"filter\" });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (t.breaker && !t.breaker.canExecute()) {\n\t\t\t\t\tskipped.push({ name: t.name, reason: \"breaker\" });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst resp = await firstValueFrom(fromAny(t.adapter.invoke(messages, invokeOpts)));\n\t\t\t\t\tt.breaker?.recordSuccess();\n\t\t\t\t\treturn { ...resp, metadata: { ...(resp.metadata ?? {}), tier: t.name } };\n\t\t\t\t} catch (err) {\n\t\t\t\t\tfailed.set(t.name, err);\n\t\t\t\t\tt.breaker?.recordFailure(err);\n\t\t\t\t\tconst next = resolved[i + 1];\n\t\t\t\t\tif (next) opts.onFallback?.(t.name, next.name, err);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst report: CascadeExhaustionReport = { skipped, failed };\n\t\t\topts.onExhausted?.(report);\n\t\t\tthrow new AllTiersExhaustedError(report);\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst skipped: Array<{ name: string; reason: \"filter\" | \"breaker\" }> = [];\n\t\t\tconst failed = new Map<string, unknown>();\n\t\t\tfor (let i = 0; i < resolved.length; i++) {\n\t\t\t\tconst t = resolved[i];\n\t\t\t\tif (t.filter && !t.filter(messages, invokeOpts)) {\n\t\t\t\t\tskipped.push({ name: t.name, reason: \"filter\" });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (t.breaker && !t.breaker.canExecute()) {\n\t\t\t\t\tskipped.push({ name: t.name, reason: \"breaker\" });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlet yieldedAny = false;\n\t\t\t\ttry {\n\t\t\t\t\tfor await (const delta of t.adapter.stream(messages, invokeOpts)) {\n\t\t\t\t\t\tyieldedAny = true;\n\t\t\t\t\t\tyield delta;\n\t\t\t\t\t}\n\t\t\t\t\tt.breaker?.recordSuccess();\n\t\t\t\t\treturn;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tfailed.set(t.name, err);\n\t\t\t\t\tt.breaker?.recordFailure(err);\n\t\t\t\t\tif (yieldedAny || !streamRetryBeforeFirstChunk) {\n\t\t\t\t\t\t// Past first chunk — stream commitment. Propagate immediately.\n\t\t\t\t\t\t// Consumers handle the thrown error in their catch; no synthetic\n\t\t\t\t\t\t// finish delta is emitted (see JSDoc at top of file). We do NOT\n\t\t\t\t\t\t// call `onExhausted` here because other tiers were never tried —\n\t\t\t\t\t\t// the error is a single-tier commitment failure, not a\n\t\t\t\t\t\t// \"no-tier-worked\" condition.\n\t\t\t\t\t\tthrow err;\n\t\t\t\t\t}\n\t\t\t\t\tconst next = resolved[i + 1];\n\t\t\t\t\tif (next) opts.onFallback?.(t.name, next.name, err);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst report: CascadeExhaustionReport = { skipped, failed };\n\t\t\topts.onExhausted?.(report);\n\t\t\tthrow new AllTiersExhaustedError(report);\n\t\t},\n\t};\n\twithLayer(cascade, `cascade[${resolved.map((t) => t.name).join(\",\")}]`);\n\treturn cascade;\n}\n\n/**\n * Tiny type-safe constructor for an {@link AdapterTier}. Cleans up the\n * heterogeneous array-type cast users (and `browser-presets.ts`) had to write\n * by hand. Per Wave A Unit 13 decision.\n *\n * @example\n * ```ts\n * cascadingLlmAdapter([\n * tier(\"local\", webllmAdapter(...)),\n * tier(\"cloud\", anthropicAdapter(...), { breaker: { failureThreshold: 5 } }),\n * ]);\n * ```\n *\n * @category ai\n */\nexport function tier(\n\tname: string,\n\tadapter: LLMAdapter,\n\topts?: { breaker?: CircuitBreakerOptions | CircuitBreaker; filter?: AdapterTier[\"filter\"] },\n): AdapterTier {\n\tconst out: AdapterTier = { name, adapter };\n\tif (opts?.breaker) out.breaker = opts.breaker;\n\tif (opts?.filter) out.filter = opts.filter;\n\treturn out;\n}\n","/**\n * Circuit breaker — open/half-open/closed state machine + companion bundle.\n *\n * - {@link circuitBreaker} returns a synchronous breaker handle (counters,\n * state machine, optional reactive-options subscription).\n * - {@link withBreaker} wraps a `Node<T>` and surfaces a reactive\n * `Node<CircuitState>` companion (`bundle.breakerState`) for telemetry.\n */\n\nimport {\n\tCOMPLETE,\n\tDATA,\n\tDIRTY,\n\tERROR,\n\tfactoryTag,\n\tmonotonicNs,\n\ttype Node,\n\tnode,\n\tRESOLVED,\n} from \"@graphrefly/pure-ts/core\";\nimport {\n\tclampNonNegative,\n\tisNode,\n\tmsgVal,\n\ttype NodeOrValue,\n\toperatorOpts,\n} from \"../../base/resilience/_internal.js\";\nimport { type BackoffStrategy, NS_PER_SEC } from \"../../base/resilience/backoff.js\";\nimport type { GateState } from \"./gate-state.js\";\n\nexport type CircuitState = \"closed\" | \"open\" | \"half-open\";\n\n/**\n * Lifecycle-shaped state companion emitted by {@link withBreaker}\n * (DS-13.5.B, locked 2026-05-01). Pre-1.0 break vs the prior\n * `Node<CircuitState>` (string-only) shape.\n *\n * `status` extends {@link GateState} with `\"half-open\"`. The numeric\n * fields surface the breaker's full internal state for telemetry and\n * `describe()` traversal.\n *\n * @category extra/resilience\n */\nexport interface BreakerState {\n\treadonly status: GateState | \"half-open\";\n\treadonly failureCount: number;\n\treadonly openCycle: number;\n\treadonly lastOpenedAtNs: number;\n\treadonly halfOpenAttempts: number;\n\treadonly lastCooldownNs: number;\n}\n\n/**\n * Thrown when {@link withBreaker} is configured with `onOpen: \"error\"` and the breaker rejects work.\n *\n * @category extra\n */\nexport class CircuitOpenError extends Error {\n\toverride name = \"CircuitOpenError\";\n\tconstructor() {\n\t\tsuper(\"Circuit breaker is open\");\n\t}\n}\n\nexport interface CircuitBreakerOptions {\n\t/** Number of consecutive failures before opening. Default: 5. */\n\tfailureThreshold?: number;\n\t/** Base cooldown in nanoseconds before transitioning to half-open. Default: 30s. */\n\tcooldownNs?: number;\n\t/** Backoff strategy for cooldown escalation across consecutive open cycles. Overrides `cooldownNs` when provided. */\n\tcooldown?: BackoffStrategy;\n\t/** Max trial requests allowed in half-open state. Default: 1. */\n\thalfOpenMax?: number;\n\t/**\n\t * Clock function returning **nanoseconds** with `monotonicNs()` semantics\n\t * (monotonically non-decreasing; suitable for elapsed-time arithmetic — never\n\t * use `Date.now()` because wall-clock skew can flip elapsed math negative).\n\t * Default: `monotonicNs` from `core/clock`. Override for deterministic tests.\n\t */\n\tnow?: () => number;\n}\n\nexport interface CircuitBreaker {\n\t/** Whether a request should be allowed through. Triggers open→half-open transition when cooldown expires. */\n\tcanExecute(): boolean;\n\t/** Record a successful execution. Resets to closed. */\n\trecordSuccess(): void;\n\t/** Record a failed execution. May transition to open. */\n\trecordFailure(error?: unknown): void;\n\t/**\n\t * Current circuit state (read-only, does not trigger transitions).\n\t *\n\t * **Telemetry:** wrap with {@link withBreaker} to surface this as a reactive\n\t * `Node<CircuitState>` companion (`bundle.breakerState`) — every state\n\t * transition (`closed`/`open`/`half-open`) emits to subscribers.\n\t */\n\treadonly state: CircuitState;\n\t/** Number of consecutive failures in the current closed period. */\n\treadonly failureCount: number;\n\t/** Manually reset to closed state, clearing all counters. */\n\treset(): void;\n\t/**\n\t * Release the reactive-options subscription (Tier 6.5 3.2.4, 2026-04-29).\n\t * No-op when constructed with static options. Call when retiring a\n\t * breaker whose options came from a `Node<CircuitBreakerOptions>` to\n\t * avoid leaking the option-Node subscription.\n\t */\n\tdispose(): void;\n}\n\n/**\n * Factory for a synchronous circuit breaker with `closed`, `open`, and `half-open` states.\n *\n * Supports escalating cooldown via an optional {@link BackoffStrategy} — each consecutive\n * open→half-open→open cycle increments the backoff attempt.\n *\n * @param options - Threshold, cooldown, half-open limit, and optional clock\n * override; OR a `Node<CircuitBreakerOptions>` carrying the same shape\n * reactively (Tier 6.5 3.2.4).\n * @returns {@link CircuitBreaker} instance.\n *\n * @remarks\n * **Timing:** Uses `monotonicNs()` by default (nanoseconds). Override `now` for tests.\n *\n * **Reactive options (locked semantics, Tier 6.5 3.2.4, 2026-04-29).**\n * When `options` is a `Node<CircuitBreakerOptions>`, the breaker\n * subscribes at construction and re-reads `failureThreshold` /\n * `cooldownNs` / `cooldown` / `halfOpenMax` / `now` on each DATA. **An\n * option swap RESETS the breaker to `\"closed\"`** with all counters\n * cleared — operators tuning a runaway breaker get a clean baseline.\n * If retaining failure history across re-tunings matters, derive a new\n * breaker per-tuning instead. Call `breaker.dispose()` when retiring to\n * release the option-Node subscription.\n *\n * @example\n * ```ts\n * import { circuitBreaker, exponential, NS_PER_SEC } from \"@graphrefly/graphrefly-ts\";\n *\n * const b = circuitBreaker({\n * failureThreshold: 3,\n * cooldown: exponential({ baseNs: 1 * NS_PER_SEC }),\n * });\n * ```\n *\n * @category extra\n */\nexport function circuitBreaker(options?: NodeOrValue<CircuitBreakerOptions>): CircuitBreaker {\n\tlet threshold = 5;\n\tlet baseCooldownNs = 30 * NS_PER_SEC;\n\tlet cooldownStrategy: BackoffStrategy | null = null;\n\tlet halfOpenMax = 1;\n\tlet now: () => number = monotonicNs;\n\n\tfunction applyOptions(o: CircuitBreakerOptions | undefined): void {\n\t\tthreshold = Math.max(1, o?.failureThreshold ?? 5);\n\t\tbaseCooldownNs = clampNonNegative(o?.cooldownNs ?? 30 * NS_PER_SEC);\n\t\tcooldownStrategy = o?.cooldown ?? null;\n\t\thalfOpenMax = Math.max(1, o?.halfOpenMax ?? 1);\n\t\tnow = o?.now ?? monotonicNs;\n\t}\n\n\tlet _state: CircuitState = \"closed\";\n\tlet _failureCount = 0;\n\tlet _openCycle = 0;\n\tlet _lastOpenedAt = 0;\n\tlet _lastCooldownNs = baseCooldownNs;\n\tlet _halfOpenAttempts = 0;\n\n\t// DS-13.5.B (locked 2026-05-01): reactive option swaps preserve\n\t// internal state — no reset across rebind. `now` is mode-locked at\n\t// construction (clock override is structural); a mid-flight `now`\n\t// change is logged and skipped (the prior `now` is preserved).\n\t// Empty `{}` emits are no-ops.\n\t//\n\t// QA A2 (2026-05-03): bad-`now` mid-flight does NOT throw — sync\n\t// throw inside a subscribe callback corrupts host scheduler state\n\t// (mirrors timeout's `actions.down([[ERROR]])` rationale; sink-side\n\t// throws break the wave's dispatch contract).\n\t//\n\t// QA A8 (2026-05-03): the push-on-subscribe re-delivery of the\n\t// cached opts fires the subscribe callback once at attach time with\n\t// the same value used for the eager `applyOptions(initialOpts)`\n\t// call above. Skip the first cached emit so opts are not re-applied\n\t// twice on construction.\n\tlet initialOpts: CircuitBreakerOptions | undefined;\n\tlet optsUnsub: (() => void) | undefined;\n\tif (isNode(options)) {\n\t\tconst optsNode = options as Node<CircuitBreakerOptions>;\n\t\tinitialOpts = optsNode.cache as CircuitBreakerOptions | undefined;\n\t\tapplyOptions(initialOpts);\n\t\tconst lockedNow = initialOpts?.now;\n\t\tconst hadInitialCache = initialOpts !== undefined;\n\t\tlet firstEmit = hadInitialCache;\n\t\toptsUnsub = optsNode.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] !== DATA) continue;\n\t\t\t\tif (firstEmit) {\n\t\t\t\t\tfirstEmit = false;\n\t\t\t\t\tcontinue; // QA A8: skip push-on-subscribe replay of cached opts\n\t\t\t\t}\n\t\t\t\tconst next = m[1] as CircuitBreakerOptions | undefined;\n\t\t\t\tif (next == null || typeof next !== \"object\") continue;\n\t\t\t\tif (Object.keys(next).length === 0) continue; // empty {} no-op\n\t\t\t\tif (\"now\" in next && next.now !== lockedNow) {\n\t\t\t\t\t// QA A2: log + skip; do NOT throw inside a subscribe\n\t\t\t\t\t// callback — host scheduler corruption hazard.\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\"circuitBreaker: ignoring mid-flight `now` change — clock override is mode-locked at construction. Prior `now` preserved.\",\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// State-preserving merge: only re-apply the axes that\n\t\t\t\t// changed; preserve `_state`, `_failureCount`, etc.\n\t\t\t\tconst merged: CircuitBreakerOptions = {\n\t\t\t\t\t...(initialOpts ?? {}),\n\t\t\t\t\t...next,\n\t\t\t\t\t...(lockedNow !== undefined ? { now: lockedNow } : {}),\n\t\t\t\t};\n\t\t\t\tapplyOptions(merged);\n\t\t\t\tinitialOpts = merged;\n\t\t\t}\n\t\t});\n\t} else {\n\t\tapplyOptions(options as CircuitBreakerOptions | undefined);\n\t}\n\t_lastCooldownNs = baseCooldownNs;\n\n\tfunction getCooldownNs(): number {\n\t\tif (!cooldownStrategy) return baseCooldownNs;\n\t\tconst delayNs = cooldownStrategy(_openCycle);\n\t\treturn delayNs !== null ? delayNs : baseCooldownNs;\n\t}\n\n\tfunction transitionToOpen(): void {\n\t\t_state = \"open\";\n\t\t_lastCooldownNs = getCooldownNs();\n\t\t_lastOpenedAt = now();\n\t\t_halfOpenAttempts = 0;\n\t}\n\n\tconst breaker: CircuitBreaker = {\n\t\tcanExecute(): boolean {\n\t\t\tif (_state === \"closed\") return true;\n\n\t\t\tif (_state === \"open\") {\n\t\t\t\tconst elapsed = now() - _lastOpenedAt;\n\t\t\t\tif (elapsed >= _lastCooldownNs) {\n\t\t\t\t\t_state = \"half-open\";\n\t\t\t\t\t_halfOpenAttempts = 1;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (_halfOpenAttempts < halfOpenMax) {\n\t\t\t\t_halfOpenAttempts++;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\n\t\trecordSuccess(): void {\n\t\t\tif (_state === \"half-open\") {\n\t\t\t\t_state = \"closed\";\n\t\t\t\t_failureCount = 0;\n\t\t\t\t_openCycle = 0;\n\t\t\t} else if (_state === \"closed\") {\n\t\t\t\t_failureCount = 0;\n\t\t\t}\n\t\t},\n\n\t\trecordFailure(_error?: unknown): void {\n\t\t\tif (_state === \"half-open\") {\n\t\t\t\t_openCycle++;\n\t\t\t\ttransitionToOpen();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (_state === \"closed\") {\n\t\t\t\t_failureCount++;\n\t\t\t\tif (_failureCount >= threshold) {\n\t\t\t\t\ttransitionToOpen();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tget state(): CircuitState {\n\t\t\treturn _state;\n\t\t},\n\n\t\tget failureCount(): number {\n\t\t\treturn _failureCount;\n\t\t},\n\n\t\treset(): void {\n\t\t\t_state = \"closed\";\n\t\t\t_failureCount = 0;\n\t\t\t_openCycle = 0;\n\t\t\t_halfOpenAttempts = 0;\n\t\t},\n\n\t\tdispose(): void {\n\t\t\toptsUnsub?.();\n\t\t},\n\n\t\t// Internal accessors used by withBreaker for the BreakerState\n\t\t// companion (DS-13.5.B). Not part of the public CircuitBreaker\n\t\t// interface but exposed for the bundle wiring.\n\t};\n\t(breaker as unknown as { _stateSnapshot: () => BreakerState })._stateSnapshot = () => ({\n\t\tstatus: _state,\n\t\tfailureCount: _failureCount,\n\t\topenCycle: _openCycle,\n\t\tlastOpenedAtNs: _lastOpenedAt,\n\t\thalfOpenAttempts: _halfOpenAttempts,\n\t\tlastCooldownNs: _lastCooldownNs,\n\t});\n\n\treturn breaker;\n}\n\nexport type WithBreakerBundle<T> = {\n\tnode: Node<T>;\n\tbreakerState: Node<BreakerState>;\n};\n\n/**\n * Returns a unary wrapper that gates upstream `DATA` through a {@link CircuitBreaker}.\n *\n * @param breaker - Shared breaker instance (typically one per resource).\n * @param options - `onOpen: \"skip\"` emits `RESOLVED` when open; `\"error\"` emits {@link CircuitOpenError}.\n * @returns Function mapping `Node<T>` to `{ node, breakerState }` companion nodes.\n *\n * @remarks\n * **Success path:** `COMPLETE` calls {@link CircuitBreaker.recordSuccess}. **Failure path:** upstream `ERROR` calls {@link CircuitBreaker.recordFailure} and is forwarded.\n *\n * **State telemetry:** `breakerState: Node<CircuitState>` is a reactive companion that mirrors `breaker.state` — every transition (`closed`/`open`/`half-open`) emits a `DATA`. Also accessible via `node.meta.breakerState` for `describe()` traversal.\n *\n * @example\n * ```ts\n * import { state, withBreaker, circuitBreaker } from \"@graphrefly/graphrefly-ts\";\n *\n * const b = circuitBreaker({ failureThreshold: 2 });\n * const s = state(1);\n * const { node, breakerState } = withBreaker(b)(s);\n * ```\n *\n * @category extra\n */\nexport function withBreaker<T>(\n\tbreaker: CircuitBreaker,\n\toptions?: { onOpen?: \"skip\" | \"error\"; meta?: Record<string, unknown> },\n): (source: Node<T>) => WithBreakerBundle<T> {\n\tconst onOpen = options?.onOpen ?? \"skip\";\n\tconst callerMeta = options?.meta;\n\n\treturn (source: Node<T>): WithBreakerBundle<T> => {\n\t\tconst snapshot = (breaker as unknown as { _stateSnapshot?: () => BreakerState })._stateSnapshot;\n\t\tconst initialSnapshot: BreakerState = snapshot\n\t\t\t? snapshot()\n\t\t\t: {\n\t\t\t\t\tstatus: breaker.state,\n\t\t\t\t\tfailureCount: breaker.failureCount,\n\t\t\t\t\topenCycle: 0,\n\t\t\t\t\tlastOpenedAtNs: 0,\n\t\t\t\t\thalfOpenAttempts: 0,\n\t\t\t\t\tlastCooldownNs: 0,\n\t\t\t\t};\n\t\tconst wrapped = node<T>(\n\t\t\t[],\n\t\t\t(_deps, a) => {\n\t\t\t\tfunction syncState(): void {\n\t\t\t\t\tconst s = snapshot\n\t\t\t\t\t\t? snapshot()\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\tstatus: breaker.state,\n\t\t\t\t\t\t\t\tfailureCount: breaker.failureCount,\n\t\t\t\t\t\t\t\topenCycle: 0,\n\t\t\t\t\t\t\t\tlastOpenedAtNs: 0,\n\t\t\t\t\t\t\t\thalfOpenAttempts: 0,\n\t\t\t\t\t\t\t\tlastCooldownNs: 0,\n\t\t\t\t\t\t\t};\n\t\t\t\t\twrapped.meta.breakerState.down([[DIRTY], [DATA, s]]);\n\t\t\t\t}\n\n\t\t\t\tconst unsub = source.subscribe((msgs) => {\n\t\t\t\t\tfor (const m of msgs) {\n\t\t\t\t\t\tconst t = m[0];\n\t\t\t\t\t\tif (t === DIRTY) a.down([[DIRTY]]);\n\t\t\t\t\t\telse if (t === DATA) {\n\t\t\t\t\t\t\tif (breaker.canExecute()) {\n\t\t\t\t\t\t\t\tsyncState();\n\t\t\t\t\t\t\t\ta.emit(m[1] as T);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tsyncState();\n\t\t\t\t\t\t\t\tif (onOpen === \"error\") a.down([[ERROR, new CircuitOpenError()]]);\n\t\t\t\t\t\t\t\telse a.down([[RESOLVED]]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (t === RESOLVED) a.down([[RESOLVED]]);\n\t\t\t\t\t\telse if (t === COMPLETE) {\n\t\t\t\t\t\t\tbreaker.recordSuccess();\n\t\t\t\t\t\t\tsyncState();\n\t\t\t\t\t\t\ta.down([[COMPLETE]]);\n\t\t\t\t\t\t} else if (t === ERROR) {\n\t\t\t\t\t\t\tbreaker.recordFailure(msgVal(m));\n\t\t\t\t\t\t\tsyncState();\n\t\t\t\t\t\t\ta.down([m]);\n\t\t\t\t\t\t} else a.down([m]);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tsyncState();\n\t\t\t\treturn unsub;\n\t\t\t},\n\t\t\t{\n\t\t\t\t...operatorOpts(),\n\t\t\t\tmeta: {\n\t\t\t\t\t...(callerMeta ?? {}),\n\t\t\t\t\tbreakerState: initialSnapshot,\n\t\t\t\t\t...factoryTag(\"withBreaker\", { onOpen }),\n\t\t\t\t},\n\t\t\t\tcompleteWhenDepsComplete: false,\n\t\t\t\tinitial: source.cache,\n\t\t\t},\n\t\t);\n\n\t\treturn { node: wrapped, breakerState: wrapped.meta.breakerState as Node<BreakerState> };\n\t};\n}\n","/**\n * Curated `cascadingLlmAdapter` presets that depend on browser-only adapters\n * (`webllmAdapter`, `chromeNanoAdapter`).\n *\n * Split out from `routing/presets.ts` so that importing `patterns/ai` in a\n * Node bundle doesn't transitively pull in `@mlc-ai/web-llm` / Chrome Nano\n * dynamic imports, and so browser-only consumers can opt in cleanly via\n * the `@graphrefly/graphrefly/patterns/ai/browser` subpath.\n *\n * @module\n */\n\nimport { createAdapter } from \"../core/factory.js\";\nimport type { LLMAdapter } from \"../core/types.js\";\nimport { chromeNanoAdapter } from \"../providers/browser/chrome-nano.js\";\nimport { webllmAdapter } from \"../providers/browser/webllm.js\";\nimport { type CascadingLlmAdapterOptions, cascadingLlmAdapter } from \"./cascading.js\";\n\n// ---------------------------------------------------------------------------\n// Cloud-first: BYOK → WebLLM → Chrome Nano\n// ---------------------------------------------------------------------------\n\nexport interface CloudFirstPresetOptions {\n\t/** BYOK config — passed directly to `createAdapter`. */\n\tcloud: Parameters<typeof createAdapter>[0];\n\t/** WebLLM model name. Pass `null` to skip the WebLLM tier. */\n\twebllmModel?: string | null;\n\t/** Pass `null` to skip the Chrome Nano tier. */\n\tchromeNano?: boolean;\n\t/** Cascade options. */\n\tcascade?: CascadingLlmAdapterOptions;\n}\n\n/**\n * Cloud-first with local fallback: BYOK → WebLLM → Chrome Nano.\n */\nexport function cloudFirstPreset(opts: CloudFirstPresetOptions): LLMAdapter {\n\tconst tiers = [{ name: \"cloud\", adapter: createAdapter(opts.cloud) }];\n\tif (opts.webllmModel) {\n\t\ttiers.push({ name: \"webllm\", adapter: webllmAdapter({ model: opts.webllmModel }) });\n\t}\n\tif (opts.chromeNano !== false) {\n\t\ttiers.push({\n\t\t\tname: \"chrome-nano\",\n\t\t\tadapter: chromeNanoAdapter(),\n\t\t\tfilter: (_msgs, iOpts) => !iOpts?.tools || iOpts.tools.length === 0,\n\t\t} as Parameters<typeof cascadingLlmAdapter>[0][number]);\n\t}\n\treturn cascadingLlmAdapter(tiers, opts.cascade);\n}\n\n// ---------------------------------------------------------------------------\n// Local-first: Ollama → WebLLM → Chrome Nano\n// ---------------------------------------------------------------------------\n\nexport interface LocalFirstPresetOptions {\n\t/** Ollama model. */\n\tollamaModel: string;\n\t/** Ollama base URL. Default http://localhost:11434/v1. */\n\tollamaBaseURL?: string;\n\twebllmModel?: string | null;\n\tchromeNano?: boolean;\n\tcascade?: CascadingLlmAdapterOptions;\n}\n\n/**\n * Local-first: nothing leaves the machine. Ollama → WebLLM → Chrome Nano.\n */\nexport function localFirstPreset(opts: LocalFirstPresetOptions): LLMAdapter {\n\tconst tiers = [\n\t\t{\n\t\t\tname: \"ollama\",\n\t\t\tadapter: createAdapter({\n\t\t\t\tprovider: \"ollama\",\n\t\t\t\tmodel: opts.ollamaModel,\n\t\t\t\tbaseURL: opts.ollamaBaseURL,\n\t\t\t}),\n\t\t},\n\t];\n\tif (opts.webllmModel) {\n\t\ttiers.push({ name: \"webllm\", adapter: webllmAdapter({ model: opts.webllmModel }) });\n\t}\n\tif (opts.chromeNano !== false) {\n\t\ttiers.push({\n\t\t\tname: \"chrome-nano\",\n\t\t\tadapter: chromeNanoAdapter(),\n\t\t\tfilter: (_msgs, iOpts) => !iOpts?.tools || iOpts.tools.length === 0,\n\t\t} as Parameters<typeof cascadingLlmAdapter>[0][number]);\n\t}\n\treturn cascadingLlmAdapter(tiers, opts.cascade);\n}\n\n// ---------------------------------------------------------------------------\n// Offline: WebLLM → Chrome Nano (no network)\n// ---------------------------------------------------------------------------\n\nexport interface OfflinePresetOptions {\n\twebllmModel: string;\n\tchromeNano?: boolean;\n\tcascade?: CascadingLlmAdapterOptions;\n}\n\nexport function offlinePreset(opts: OfflinePresetOptions): LLMAdapter {\n\tconst tiers = [{ name: \"webllm\", adapter: webllmAdapter({ model: opts.webllmModel }) }];\n\tif (opts.chromeNano !== false) {\n\t\ttiers.push({\n\t\t\tname: \"chrome-nano\",\n\t\t\tadapter: chromeNanoAdapter(),\n\t\t\tfilter: (_msgs, iOpts) => !iOpts?.tools || iOpts.tools.length === 0,\n\t\t} as Parameters<typeof cascadingLlmAdapter>[0][number]);\n\t}\n\treturn cascadingLlmAdapter(tiers, opts.cascade);\n}\n"],"mappings":"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","names":["import_core","import_core","makeAbortError","mapUsage","import_core","import_core","import_core","makeAbortError","import_core","import_extra","import_core","import_extra","import_core","import_core","import_extra","raw","import_core","import_extra","import_core","mapUsage","toLLMResponse","import_core","mapUsage","toLLMResponse","import_extra","import_core"]}