@graphrefly/graphrefly 0.45.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 (714) hide show
  1. package/README.md +1 -2
  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/base/render/index.d.cts +227 -0
  47. package/dist/base/render/index.d.ts +227 -0
  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/base/sources/index.d.cts +357 -0
  65. package/dist/base/sources/index.d.ts +357 -0
  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/base/sources/node/index.d.cts +185 -0
  71. package/dist/base/sources/node/index.d.ts +185 -0
  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-CSSbKGrJ.d.ts +199 -0
  89. package/dist/cascading-baGkiihI.d.cts +199 -0
  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 +3083 -2
  239. package/dist/compat/index.cjs.map +1 -1
  240. package/dist/compat/index.d.cts +116 -1
  241. package/dist/compat/index.d.ts +116 -1
  242. package/dist/compat/index.js +175 -2
  243. package/dist/compat/index.js.map +1 -1
  244. package/dist/compat/jotai/index.cjs +130 -2
  245. package/dist/compat/jotai/index.cjs.map +1 -1
  246. package/dist/compat/jotai/index.d.cts +2 -1
  247. package/dist/compat/jotai/index.d.ts +2 -1
  248. package/dist/compat/jotai/index.js +7 -2
  249. package/dist/compat/jotai/index.js.map +1 -1
  250. package/dist/compat/nanostores/index.cjs +186 -2
  251. package/dist/compat/nanostores/index.cjs.map +1 -1
  252. package/dist/compat/nanostores/index.d.cts +2 -1
  253. package/dist/compat/nanostores/index.d.ts +2 -1
  254. package/dist/compat/nanostores/index.js +21 -2
  255. package/dist/compat/nanostores/index.js.map +1 -1
  256. package/dist/compat/nestjs/index.cjs +2224 -2
  257. package/dist/compat/nestjs/index.cjs.map +1 -1
  258. package/dist/compat/nestjs/index.d.cts +10 -1
  259. package/dist/compat/nestjs/index.d.ts +10 -1
  260. package/dist/compat/nestjs/index.js +77 -2
  261. package/dist/compat/nestjs/index.js.map +1 -1
  262. package/dist/compat/react/index.cjs +95 -2
  263. package/dist/compat/react/index.cjs.map +1 -1
  264. package/dist/compat/react/index.d.cts +2 -1
  265. package/dist/compat/react/index.d.ts +2 -1
  266. package/dist/compat/react/index.js +11 -2
  267. package/dist/compat/react/index.js.map +1 -1
  268. package/dist/compat/solid/index.cjs +82 -2
  269. package/dist/compat/solid/index.cjs.map +1 -1
  270. package/dist/compat/solid/index.d.cts +2 -1
  271. package/dist/compat/solid/index.d.ts +2 -1
  272. package/dist/compat/solid/index.js +11 -2
  273. package/dist/compat/solid/index.js.map +1 -1
  274. package/dist/compat/svelte/index.cjs +85 -2
  275. package/dist/compat/svelte/index.cjs.map +1 -1
  276. package/dist/compat/svelte/index.d.cts +2 -1
  277. package/dist/compat/svelte/index.d.ts +2 -1
  278. package/dist/compat/svelte/index.js +11 -2
  279. package/dist/compat/svelte/index.js.map +1 -1
  280. package/dist/compat/vue/index.cjs +100 -2
  281. package/dist/compat/vue/index.cjs.map +1 -1
  282. package/dist/compat/vue/index.d.cts +3 -1
  283. package/dist/compat/vue/index.d.ts +3 -1
  284. package/dist/compat/vue/index.js +11 -2
  285. package/dist/compat/vue/index.js.map +1 -1
  286. package/dist/compat/zustand/index.cjs +50 -2
  287. package/dist/compat/zustand/index.cjs.map +1 -1
  288. package/dist/compat/zustand/index.d.cts +2 -1
  289. package/dist/compat/zustand/index.d.ts +2 -1
  290. package/dist/compat/zustand/index.js +7 -2
  291. package/dist/compat/zustand/index.js.map +1 -1
  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-Bx46zqky.d.cts +243 -0
  297. package/dist/fallback-pIWW8A2d.d.ts +243 -0
  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-5SU_O78r.d.cts +754 -0
  301. package/dist/index-B6pxYJzO.d.cts +36 -0
  302. package/dist/index-B6pxYJzO.d.ts +36 -0
  303. package/dist/index-BFsng6v1.d.cts +44 -0
  304. package/dist/index-BFsng6v1.d.ts +44 -0
  305. package/dist/index-Bg-LwEt-.d.cts +45 -0
  306. package/dist/index-Bg-LwEt-.d.ts +45 -0
  307. package/dist/index-Brp888t0.d.cts +127 -0
  308. package/dist/index-Brp888t0.d.ts +127 -0
  309. package/dist/index-CDfk6jHN.d.cts +37 -0
  310. package/dist/index-CDfk6jHN.d.ts +37 -0
  311. package/dist/index-CEXCtYYJ.d.ts +754 -0
  312. package/dist/index-DLAxYaN5.d.cts +169 -0
  313. package/dist/index-DLAxYaN5.d.ts +169 -0
  314. package/dist/index-DeWbQzMe.d.cts +34 -0
  315. package/dist/index-DeWbQzMe.d.ts +34 -0
  316. package/dist/index-dX9IzPqj.d.cts +86 -0
  317. package/dist/index-dX9IzPqj.d.ts +86 -0
  318. package/dist/index.cjs +25950 -0
  319. package/dist/index.cjs.map +1 -1
  320. package/dist/index.d.cts +56 -42
  321. package/dist/index.d.ts +56 -42
  322. package/dist/index.js +849 -0
  323. package/dist/index.js.map +1 -1
  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-BXQoW1P-.d.cts +36 -0
  329. package/dist/observable-BXQoW1P-.d.ts +36 -0
  330. package/dist/pipeline-graph-Ce47CB6Y.d.cts +145 -0
  331. package/dist/pipeline-graph-DXCwY9vG.d.ts +145 -0
  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-fswlBUvX.d.cts +195 -0
  365. package/dist/reactive-layout-fswlBUvX.d.ts +195 -0
  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-BB5Lw-pB.d.cts +442 -0
  381. package/dist/types-BB5Lw-pB.d.ts +442 -0
  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/utils/ai/browser.d.cts +129 -0
  387. package/dist/utils/ai/browser.d.ts +129 -0
  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/utils/ai/index.d.cts +1777 -0
  393. package/dist/utils/ai/index.d.ts +1777 -0
  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/utils/ai/node.d.cts +57 -0
  399. package/dist/utils/ai/node.d.ts +57 -0
  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/utils/cqrs/index.d.cts +438 -0
  405. package/dist/utils/cqrs/index.d.ts +438 -0
  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/utils/demo-shell/index.d.cts +90 -0
  411. package/dist/utils/demo-shell/index.d.ts +90 -0
  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/utils/domain-templates/index.d.cts +214 -0
  417. package/dist/utils/domain-templates/index.d.ts +214 -0
  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/utils/graphspec/index.d.cts +449 -0
  423. package/dist/utils/graphspec/index.d.ts +449 -0
  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/utils/job-queue/index.d.cts +200 -0
  447. package/dist/utils/job-queue/index.d.ts +200 -0
  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/utils/memory/index.d.cts +582 -0
  453. package/dist/utils/memory/index.d.ts +582 -0
  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/utils/process/index.d.cts +411 -0
  471. package/dist/utils/process/index.d.ts +411 -0
  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/utils/reactive-layout/index.d.cts +492 -0
  477. package/dist/utils/reactive-layout/index.d.ts +492 -0
  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/utils/reduction/index.d.cts +102 -0
  483. package/dist/utils/reduction/index.d.ts +102 -0
  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/utils/surface/index.d.cts +240 -0
  495. package/dist/utils/surface/index.d.ts +240 -0
  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 +293 -237
  505. package/dist/core/index.cjs +0 -21
  506. package/dist/core/index.cjs.map +0 -1
  507. package/dist/core/index.d.cts +0 -1
  508. package/dist/core/index.d.ts +0 -1
  509. package/dist/core/index.js +0 -3
  510. package/dist/core/index.js.map +0 -1
  511. package/dist/extra/browser.cjs +0 -21
  512. package/dist/extra/browser.cjs.map +0 -1
  513. package/dist/extra/browser.d.cts +0 -1
  514. package/dist/extra/browser.d.ts +0 -1
  515. package/dist/extra/browser.js +0 -3
  516. package/dist/extra/browser.js.map +0 -1
  517. package/dist/extra/index.cjs +0 -21
  518. package/dist/extra/index.cjs.map +0 -1
  519. package/dist/extra/index.d.cts +0 -1
  520. package/dist/extra/index.d.ts +0 -1
  521. package/dist/extra/index.js +0 -3
  522. package/dist/extra/index.js.map +0 -1
  523. package/dist/extra/node.cjs +0 -21
  524. package/dist/extra/node.cjs.map +0 -1
  525. package/dist/extra/node.d.cts +0 -1
  526. package/dist/extra/node.d.ts +0 -1
  527. package/dist/extra/node.js +0 -3
  528. package/dist/extra/node.js.map +0 -1
  529. package/dist/extra/operators.cjs +0 -21
  530. package/dist/extra/operators.cjs.map +0 -1
  531. package/dist/extra/operators.d.cts +0 -1
  532. package/dist/extra/operators.d.ts +0 -1
  533. package/dist/extra/operators.js +0 -3
  534. package/dist/extra/operators.js.map +0 -1
  535. package/dist/extra/reactive.cjs +0 -21
  536. package/dist/extra/reactive.cjs.map +0 -1
  537. package/dist/extra/reactive.d.cts +0 -1
  538. package/dist/extra/reactive.d.ts +0 -1
  539. package/dist/extra/reactive.js +0 -3
  540. package/dist/extra/reactive.js.map +0 -1
  541. package/dist/extra/render/index.cjs +0 -21
  542. package/dist/extra/render/index.cjs.map +0 -1
  543. package/dist/extra/render/index.d.cts +0 -1
  544. package/dist/extra/render/index.d.ts +0 -1
  545. package/dist/extra/render/index.js +0 -3
  546. package/dist/extra/render/index.js.map +0 -1
  547. package/dist/extra/sources.cjs +0 -21
  548. package/dist/extra/sources.cjs.map +0 -1
  549. package/dist/extra/sources.d.cts +0 -1
  550. package/dist/extra/sources.d.ts +0 -1
  551. package/dist/extra/sources.js +0 -3
  552. package/dist/extra/sources.js.map +0 -1
  553. package/dist/extra/storage-browser.cjs +0 -21
  554. package/dist/extra/storage-browser.cjs.map +0 -1
  555. package/dist/extra/storage-browser.d.cts +0 -1
  556. package/dist/extra/storage-browser.d.ts +0 -1
  557. package/dist/extra/storage-browser.js +0 -3
  558. package/dist/extra/storage-browser.js.map +0 -1
  559. package/dist/extra/storage-core.cjs +0 -21
  560. package/dist/extra/storage-core.cjs.map +0 -1
  561. package/dist/extra/storage-core.d.cts +0 -1
  562. package/dist/extra/storage-core.d.ts +0 -1
  563. package/dist/extra/storage-core.js +0 -3
  564. package/dist/extra/storage-core.js.map +0 -1
  565. package/dist/extra/storage-node.cjs +0 -21
  566. package/dist/extra/storage-node.cjs.map +0 -1
  567. package/dist/extra/storage-node.d.cts +0 -1
  568. package/dist/extra/storage-node.d.ts +0 -1
  569. package/dist/extra/storage-node.js +0 -3
  570. package/dist/extra/storage-node.js.map +0 -1
  571. package/dist/extra/storage-tiers-browser.cjs +0 -21
  572. package/dist/extra/storage-tiers-browser.cjs.map +0 -1
  573. package/dist/extra/storage-tiers-browser.d.cts +0 -1
  574. package/dist/extra/storage-tiers-browser.d.ts +0 -1
  575. package/dist/extra/storage-tiers-browser.js +0 -3
  576. package/dist/extra/storage-tiers-browser.js.map +0 -1
  577. package/dist/extra/storage-tiers-node.cjs +0 -21
  578. package/dist/extra/storage-tiers-node.cjs.map +0 -1
  579. package/dist/extra/storage-tiers-node.d.cts +0 -1
  580. package/dist/extra/storage-tiers-node.d.ts +0 -1
  581. package/dist/extra/storage-tiers-node.js +0 -3
  582. package/dist/extra/storage-tiers-node.js.map +0 -1
  583. package/dist/extra/storage-tiers.cjs +0 -21
  584. package/dist/extra/storage-tiers.cjs.map +0 -1
  585. package/dist/extra/storage-tiers.d.cts +0 -1
  586. package/dist/extra/storage-tiers.d.ts +0 -1
  587. package/dist/extra/storage-tiers.js +0 -3
  588. package/dist/extra/storage-tiers.js.map +0 -1
  589. package/dist/extra/storage-wal.cjs +0 -21
  590. package/dist/extra/storage-wal.cjs.map +0 -1
  591. package/dist/extra/storage-wal.d.cts +0 -1
  592. package/dist/extra/storage-wal.d.ts +0 -1
  593. package/dist/extra/storage-wal.js +0 -3
  594. package/dist/extra/storage-wal.js.map +0 -1
  595. package/dist/graph/index.cjs +0 -21
  596. package/dist/graph/index.cjs.map +0 -1
  597. package/dist/graph/index.d.cts +0 -1
  598. package/dist/graph/index.d.ts +0 -1
  599. package/dist/graph/index.js +0 -3
  600. package/dist/graph/index.js.map +0 -1
  601. package/dist/patterns/ai/browser.cjs +0 -21
  602. package/dist/patterns/ai/browser.cjs.map +0 -1
  603. package/dist/patterns/ai/browser.d.cts +0 -1
  604. package/dist/patterns/ai/browser.d.ts +0 -1
  605. package/dist/patterns/ai/browser.js +0 -3
  606. package/dist/patterns/ai/browser.js.map +0 -1
  607. package/dist/patterns/ai/index.cjs +0 -21
  608. package/dist/patterns/ai/index.cjs.map +0 -1
  609. package/dist/patterns/ai/index.d.cts +0 -1
  610. package/dist/patterns/ai/index.d.ts +0 -1
  611. package/dist/patterns/ai/index.js +0 -3
  612. package/dist/patterns/ai/index.js.map +0 -1
  613. package/dist/patterns/ai/node.cjs +0 -21
  614. package/dist/patterns/ai/node.cjs.map +0 -1
  615. package/dist/patterns/ai/node.d.cts +0 -1
  616. package/dist/patterns/ai/node.d.ts +0 -1
  617. package/dist/patterns/ai/node.js +0 -3
  618. package/dist/patterns/ai/node.js.map +0 -1
  619. package/dist/patterns/cqrs/index.cjs +0 -21
  620. package/dist/patterns/cqrs/index.cjs.map +0 -1
  621. package/dist/patterns/cqrs/index.d.cts +0 -1
  622. package/dist/patterns/cqrs/index.d.ts +0 -1
  623. package/dist/patterns/cqrs/index.js +0 -3
  624. package/dist/patterns/cqrs/index.js.map +0 -1
  625. package/dist/patterns/demo-shell/index.cjs +0 -21
  626. package/dist/patterns/demo-shell/index.cjs.map +0 -1
  627. package/dist/patterns/demo-shell/index.d.cts +0 -1
  628. package/dist/patterns/demo-shell/index.d.ts +0 -1
  629. package/dist/patterns/demo-shell/index.js +0 -3
  630. package/dist/patterns/demo-shell/index.js.map +0 -1
  631. package/dist/patterns/domain-templates/index.cjs +0 -21
  632. package/dist/patterns/domain-templates/index.cjs.map +0 -1
  633. package/dist/patterns/domain-templates/index.d.cts +0 -1
  634. package/dist/patterns/domain-templates/index.d.ts +0 -1
  635. package/dist/patterns/domain-templates/index.js +0 -3
  636. package/dist/patterns/domain-templates/index.js.map +0 -1
  637. package/dist/patterns/graphspec/index.cjs +0 -21
  638. package/dist/patterns/graphspec/index.cjs.map +0 -1
  639. package/dist/patterns/graphspec/index.d.cts +0 -1
  640. package/dist/patterns/graphspec/index.d.ts +0 -1
  641. package/dist/patterns/graphspec/index.js +0 -3
  642. package/dist/patterns/graphspec/index.js.map +0 -1
  643. package/dist/patterns/harness/index.cjs +0 -21
  644. package/dist/patterns/harness/index.cjs.map +0 -1
  645. package/dist/patterns/harness/index.d.cts +0 -1
  646. package/dist/patterns/harness/index.d.ts +0 -1
  647. package/dist/patterns/harness/index.js +0 -3
  648. package/dist/patterns/harness/index.js.map +0 -1
  649. package/dist/patterns/inspect/index.cjs +0 -21
  650. package/dist/patterns/inspect/index.cjs.map +0 -1
  651. package/dist/patterns/inspect/index.d.cts +0 -1
  652. package/dist/patterns/inspect/index.d.ts +0 -1
  653. package/dist/patterns/inspect/index.js +0 -3
  654. package/dist/patterns/inspect/index.js.map +0 -1
  655. package/dist/patterns/job-queue/index.cjs +0 -21
  656. package/dist/patterns/job-queue/index.cjs.map +0 -1
  657. package/dist/patterns/job-queue/index.d.cts +0 -1
  658. package/dist/patterns/job-queue/index.d.ts +0 -1
  659. package/dist/patterns/job-queue/index.js +0 -3
  660. package/dist/patterns/job-queue/index.js.map +0 -1
  661. package/dist/patterns/memory/index.cjs +0 -21
  662. package/dist/patterns/memory/index.cjs.map +0 -1
  663. package/dist/patterns/memory/index.d.cts +0 -1
  664. package/dist/patterns/memory/index.d.ts +0 -1
  665. package/dist/patterns/memory/index.js +0 -3
  666. package/dist/patterns/memory/index.js.map +0 -1
  667. package/dist/patterns/messaging/index.cjs +0 -21
  668. package/dist/patterns/messaging/index.cjs.map +0 -1
  669. package/dist/patterns/messaging/index.d.cts +0 -1
  670. package/dist/patterns/messaging/index.d.ts +0 -1
  671. package/dist/patterns/messaging/index.js +0 -3
  672. package/dist/patterns/messaging/index.js.map +0 -1
  673. package/dist/patterns/orchestration/index.cjs +0 -21
  674. package/dist/patterns/orchestration/index.cjs.map +0 -1
  675. package/dist/patterns/orchestration/index.d.cts +0 -1
  676. package/dist/patterns/orchestration/index.d.ts +0 -1
  677. package/dist/patterns/orchestration/index.js +0 -3
  678. package/dist/patterns/orchestration/index.js.map +0 -1
  679. package/dist/patterns/process/index.cjs +0 -21
  680. package/dist/patterns/process/index.cjs.map +0 -1
  681. package/dist/patterns/process/index.d.cts +0 -1
  682. package/dist/patterns/process/index.d.ts +0 -1
  683. package/dist/patterns/process/index.js +0 -3
  684. package/dist/patterns/process/index.js.map +0 -1
  685. package/dist/patterns/reactive-layout/index.cjs +0 -21
  686. package/dist/patterns/reactive-layout/index.cjs.map +0 -1
  687. package/dist/patterns/reactive-layout/index.d.cts +0 -1
  688. package/dist/patterns/reactive-layout/index.d.ts +0 -1
  689. package/dist/patterns/reactive-layout/index.js +0 -3
  690. package/dist/patterns/reactive-layout/index.js.map +0 -1
  691. package/dist/patterns/reduction/index.cjs +0 -21
  692. package/dist/patterns/reduction/index.cjs.map +0 -1
  693. package/dist/patterns/reduction/index.d.cts +0 -1
  694. package/dist/patterns/reduction/index.d.ts +0 -1
  695. package/dist/patterns/reduction/index.js +0 -3
  696. package/dist/patterns/reduction/index.js.map +0 -1
  697. package/dist/patterns/surface/index.cjs +0 -21
  698. package/dist/patterns/surface/index.cjs.map +0 -1
  699. package/dist/patterns/surface/index.d.cts +0 -1
  700. package/dist/patterns/surface/index.d.ts +0 -1
  701. package/dist/patterns/surface/index.js +0 -3
  702. package/dist/patterns/surface/index.js.map +0 -1
  703. package/dist/patterns/topology-view/index.cjs +0 -21
  704. package/dist/patterns/topology-view/index.cjs.map +0 -1
  705. package/dist/patterns/topology-view/index.d.cts +0 -1
  706. package/dist/patterns/topology-view/index.d.ts +0 -1
  707. package/dist/patterns/topology-view/index.js +0 -3
  708. package/dist/patterns/topology-view/index.js.map +0 -1
  709. package/dist/testing/index.cjs +0 -21
  710. package/dist/testing/index.cjs.map +0 -1
  711. package/dist/testing/index.d.cts +0 -1
  712. package/dist/testing/index.d.ts +0 -1
  713. package/dist/testing/index.js +0 -3
  714. package/dist/testing/index.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/ai/adapters/core/capabilities.ts","../src/utils/ai/adapters/core/observable.ts","../src/utils/ai/adapters/core/types.ts","../src/utils/ai/adapters/core/pricing.ts","../src/utils/ai/adapters/middleware/breaker.ts","../src/utils/ai/adapters/middleware/budget-gate.ts","../src/utils/ai/adapters/middleware/dry-run.ts","../src/utils/ai/adapters/middleware/http429-parser.ts","../src/utils/ai/adapters/middleware/rate-limiter.ts","../src/utils/ai/adapters/middleware/retry.ts","../src/utils/ai/adapters/middleware/timeout.ts","../src/utils/ai/adapters/middleware/resilient-adapter.ts","../src/utils/ai/prompts/frozen-context.ts","../src/utils/ai/prompts/streaming.ts","../src/utils/ai/prompts/system-prompt.ts","../src/utils/ai/extractors/cost-meter.ts","../src/utils/ai/extractors/keyword-flag.ts","../src/utils/ai/extractors/stream-extractor.ts","../src/utils/ai/extractors/tool-call.ts","../src/utils/ai/safety/content-gate.ts","../src/utils/ai/safety/redactor.ts","../src/utils/ai/agents/handoff.ts","../src/utils/ai/agents/tool-selector.ts","../src/utils/ai/memory/admission.ts","../src/utils/ai/graph-integration/gauges-as-context.ts","../src/utils/ai/graph-integration/graph-from-spec.ts","../src/utils/ai/graph-integration/knobs-as-tools.ts","../src/utils/ai/graph-integration/suggest-strategy.ts","../src/utils/ai/graph-integration/validate-graph-def.ts"],"sourcesContent":["/**\n * Pluggable model capabilities (roadmap §9.3d).\n *\n * The library defines the **shape** of what's knowable about a model\n * (context window, rate limits, features, pricing reference) and provides\n * a registry factory. Capability **data** is user-supplied — no baked-in\n * tables, no drift-prone catalog.\n */\n\nimport type { Node } from \"@graphrefly/pure-ts/core\";\nimport { node } from \"@graphrefly/pure-ts/core\";\n\nimport { reactiveMap } from \"@graphrefly/pure-ts/extra\";\nimport type { ModelPricing } from \"./pricing.js\";\n\n// ---------------------------------------------------------------------------\n// Limits\n// ---------------------------------------------------------------------------\n\n/**\n * Rate and size limits for a single model at the user's service tier.\n *\n * Where providers expose distinct standard / batch / flex limits, register\n * each as a separate model id with its own `ModelLimits`.\n */\nexport interface ModelLimits {\n\t/** Total tokens the model can process per request (input + output). */\n\tcontextWindow?: number;\n\t/** Max input tokens if distinct from contextWindow. */\n\tmaxInputTokens?: number;\n\t/** Max generated output tokens (excludes reasoning unless provider folds them). */\n\tmaxOutputTokens?: number;\n\t/** Max reasoning/thinking tokens budget. */\n\tmaxReasoningTokens?: number;\n\t/** Minimum prompt size for prompt caching to activate. */\n\tminCacheTokens?: number;\n\t/** Requests-per-minute rate limit. */\n\trpm?: number;\n\t/** Requests-per-day rate limit. */\n\trpd?: number;\n\t/** Tokens-per-minute rate limit (input + output, per provider convention). */\n\ttpm?: number;\n\t/** Tokens-per-day rate limit. */\n\ttpd?: number;\n\t/** Max concurrent in-flight requests. */\n\tconcurrentRequests?: number;\n\t/** Provider-specific limits not covered above. */\n\textensions?: Record<string, number>;\n}\n\n// ---------------------------------------------------------------------------\n// Features\n// ---------------------------------------------------------------------------\n\nexport interface ModelFeatures {\n\ttoolUse?: boolean;\n\tvision?: boolean;\n\taudioInput?: boolean;\n\taudioOutput?: boolean;\n\treasoning?: boolean;\n\tstreaming?: boolean;\n\tpromptCache?: boolean;\n\tbatchApi?: boolean;\n\t/** Provider-specific feature flags. */\n\textensions?: Record<string, boolean>;\n}\n\n// ---------------------------------------------------------------------------\n// ModelCapabilities\n// ---------------------------------------------------------------------------\n\n/** Static facts about a model. Pricing is optional; keep a separate registry if preferred. */\nexport interface ModelCapabilities {\n\tid: string;\n\tprovider: string;\n\tpricing?: ModelPricing;\n\tlimits?: ModelLimits;\n\tfeatures?: ModelFeatures;\n\t/** Free-form metadata (release date, deprecation flag, provider notes). */\n\tmetadata?: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// CapabilitiesRegistry\n// ---------------------------------------------------------------------------\n\nexport interface CapabilitiesRegistry {\n\tlookup(provider: string, model: string): ModelCapabilities | undefined;\n\tregister(cap: ModelCapabilities): void;\n\tremove(provider: string, model: string): boolean;\n\tentries(): IterableIterator<ModelCapabilities>;\n\t// Reactive views (Unit 10 Q4) ---------------------------------------------\n\t/**\n\t * Reactive view of `(provider, model)` → `ModelCapabilities`. Re-emits\n\t * whenever any `register()` / `remove()` touches the underlying store, so\n\t * UIs and gated middleware (capability-aware retry, feature flags) can\n\t * subscribe instead of polling. Prefix fallback mirrors the imperative\n\t * `lookup()`: exact match first, then longest-prefix within provider.\n\t */\n\tlookupNode(provider: string, model: string): Node<ModelCapabilities | undefined>;\n\t/** Reactive view of every registered entry. */\n\treadonly entriesNode: Node<readonly ModelCapabilities[]>;\n\t/** Reactive slice of entries for a single provider. */\n\tbyProvider(provider: string): Node<readonly ModelCapabilities[]>;\n}\n\nfunction capKey(provider: string, model: string): string {\n\treturn `${provider}::${model}`;\n}\n\n/** Create a fresh `CapabilitiesRegistry`. Optionally seed with entries. */\nexport function createCapabilitiesRegistry(\n\tinitial?: readonly ModelCapabilities[],\n): CapabilitiesRegistry {\n\t// Reactive storage (Unit 10 Q4). We keep the imperative `lookup` fast path\n\t// (O(1) exact match + prefix fallback) by reading the bundle's snapshot via\n\t// `.cache`. Reactive views (`lookupNode`, `entriesNode`, `byProvider`) are\n\t// `derived` nodes over the bundle's `entries` node.\n\tconst bundle = reactiveMap<string, ModelCapabilities>({\n\t\tname: \"capabilitiesRegistry\",\n\t});\n\n\tconst register = (cap: ModelCapabilities): void => {\n\t\tbundle.set(capKey(cap.provider, cap.id), cap);\n\t};\n\n\tif (initial) for (const cap of initial) register(cap);\n\n\tconst lookupSync = (provider: string, model: string): ModelCapabilities | undefined => {\n\t\tconst exact = bundle.get(capKey(provider, model));\n\t\tif (exact) return exact;\n\t\t// Prefix fallback within provider via snapshot iteration. The fast\n\t\t// path (`maxSize` unset → all entries live) keeps this O(|models|).\n\t\tconst snapshot = bundle.entries.cache;\n\t\tif (!snapshot) return undefined;\n\t\tlet best: ModelCapabilities | undefined;\n\t\tfor (const [, cap] of snapshot) {\n\t\t\tif (cap.provider !== provider) continue;\n\t\t\tconst candidate = cap.id;\n\t\t\tif (model.startsWith(candidate)) {\n\t\t\t\tif (!best || candidate.length > best.id.length) {\n\t\t\t\t\tbest = cap;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn best;\n\t};\n\n\t// Reactive views — derived over the bundle's entries snapshot. Caches\n\t// per-(provider, model) pair so re-invoking `lookupNode(\"anthropic\", \"X\")`\n\t// returns the same node (keepalive stays attached, no churn).\n\t//\n\t// LRU cap protects callers that mint `lookupNode(provider, userSupplied)`\n\t// from unbounded growth. Native `Map` insertion-order iteration gives us\n\t// O(1) eviction: the oldest insertion is the first key. 128 is large\n\t// enough to cover realistic provider × model combos (every shipped\n\t// Anthropic / OpenAI / Google model fits well under this).\n\tconst LOOKUP_CACHE_MAX = 128;\n\tconst lookupCache = new Map<string, Node<ModelCapabilities | undefined>>();\n\tconst byProviderCache = new Map<string, Node<readonly ModelCapabilities[]>>();\n\tconst lruTouch = <V>(cache: Map<string, V>, key: string, value: V, max: number): void => {\n\t\t// Delete-then-reinsert moves the key to the LRU end; evict the oldest\n\t\t// (first-inserted) entry when we overflow.\n\t\tif (cache.has(key)) cache.delete(key);\n\t\tcache.set(key, value);\n\t\twhile (cache.size > max) {\n\t\t\tconst oldest = cache.keys().next().value as string | undefined;\n\t\t\tif (oldest === undefined) break;\n\t\t\tcache.delete(oldest);\n\t\t}\n\t};\n\n\tconst entriesNode = node<readonly ModelCapabilities[]>(\n\t\t[bundle.entries],\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 snapshot = data[0];\n\t\t\t// Defensive coercion: `ReactiveMapBundle.entries` always emits a\n\t\t\t// real `Map` on the live emit path, but a snapshot-restore round\n\t\t\t// trip can deliver a plain `{}` (the default codec serializes\n\t\t\t// `Map` to a non-Map shape). Without the `instanceof` guard,\n\t\t\t// `.values()` would be `undefined`. Same defense pattern as\n\t\t\t// `mapFromSnapshot` in `extra/composite.ts`.\n\t\t\tactions.emit(\n\t\t\t\tsnapshot instanceof Map\n\t\t\t\t\t? Array.from((snapshot as ReadonlyMap<string, ModelCapabilities>).values())\n\t\t\t\t\t: [],\n\t\t\t);\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tname: \"capabilitiesRegistry/entries\",\n\t\t\tinitial: [] as ModelCapabilities[],\n\t\t},\n\t);\n\n\treturn {\n\t\tregister,\n\t\tlookup: lookupSync,\n\t\tremove(provider, model) {\n\t\t\tconst existed = bundle.has(capKey(provider, model));\n\t\t\tif (existed) bundle.delete(capKey(provider, model));\n\t\t\treturn existed;\n\t\t},\n\t\tentries() {\n\t\t\t// Snapshot via bundle — matches legacy behavior.\n\t\t\tconst snapshot = bundle.entries.cache;\n\t\t\treturn (function* () {\n\t\t\t\tif (!snapshot) return;\n\t\t\t\tfor (const cap of snapshot.values()) yield cap;\n\t\t\t})();\n\t\t},\n\t\tlookupNode(provider, model) {\n\t\t\tconst cacheKey = capKey(provider, model);\n\t\t\tconst cached = lookupCache.get(cacheKey);\n\t\t\tif (cached) {\n\t\t\t\t// LRU touch: move to end so it survives eviction.\n\t\t\t\tlookupCache.delete(cacheKey);\n\t\t\t\tlookupCache.set(cacheKey, cached);\n\t\t\t\treturn cached;\n\t\t\t}\n\t\t\tconst lookupNode = node<ModelCapabilities | undefined>(\n\t\t\t\t[bundle.entries],\n\t\t\t\t(_batchData, actions) => {\n\t\t\t\t\tactions.emit(lookupSync(provider, model));\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\t\tname: `capabilitiesRegistry/lookup/${provider}::${model}`,\n\t\t\t\t\tinitial: undefined,\n\t\t\t\t},\n\t\t\t);\n\t\t\tlruTouch(lookupCache, cacheKey, lookupNode, LOOKUP_CACHE_MAX);\n\t\t\treturn lookupNode;\n\t\t},\n\t\tentriesNode,\n\t\tbyProvider(provider) {\n\t\t\tconst cached = byProviderCache.get(provider);\n\t\t\tif (cached) {\n\t\t\t\tbyProviderCache.delete(provider);\n\t\t\t\tbyProviderCache.set(provider, cached);\n\t\t\t\treturn cached;\n\t\t\t}\n\t\t\tconst providerNode = node<readonly ModelCapabilities[]>(\n\t\t\t\t[entriesNode],\n\t\t\t\t(batchData, actions, ctx) => {\n\t\t\t\t\tconst data = batchData.map((batch, i) =>\n\t\t\t\t\t\tbatch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i],\n\t\t\t\t\t);\n\t\t\t\t\tconst entries = data[0] as readonly ModelCapabilities[];\n\t\t\t\t\tactions.emit(entries.filter((c) => c.provider === provider));\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\t\tname: `capabilitiesRegistry/byProvider/${provider}`,\n\t\t\t\t\tinitial: [],\n\t\t\t\t},\n\t\t\t);\n\t\t\tlruTouch(byProviderCache, provider, providerNode, LOOKUP_CACHE_MAX);\n\t\t\treturn providerNode;\n\t\t},\n\t};\n}\n","/**\n * Observable adapter wrapper — the \"inverted statistics\" surface.\n *\n * The library emits structured facts (token counts, latency, timestamps)\n * as reactive nodes. Users compose interpretation (pricing, dashboards,\n * telemetry, budget breakers) as derived layers on top.\n */\n\nimport { monotonicNs, type Node, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { keepalive, type ReactiveLogBundle, reactiveLog } from \"@graphrefly/pure-ts/extra\";\nimport {\n\tadapterWrapper,\n\tadaptInvokeResult,\n\tbuildCallStats,\n\temptyUsageStub,\n\twithLayer,\n} from \"../_internal/wrappers.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n\tTokenUsage,\n} from \"./types.js\";\nimport { sumInputTokens, sumOutputTokens } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// CallStatsEvent\n// ---------------------------------------------------------------------------\n\n/** One call's structured statistics — emitted after `invoke()` / `stream()` settles. */\nexport interface CallStatsEvent {\n\t/** `monotonicNs()` at call completion — use for event ordering. */\n\treadonly timestamp: number;\n\t/** `wallClockNs()` at call start — use for human-readable attribution. */\n\treadonly wallClock: number;\n\treadonly provider: string;\n\treadonly model: string;\n\treadonly tier?: string;\n\treadonly usage: TokenUsage;\n\treadonly latencyMs: number;\n\t/** `\"invoke\"` or `\"stream\"`. */\n\treadonly method: \"invoke\" | \"stream\";\n\t/** Populated when the call errored — usage may be zero or partial. */\n\treadonly error?: { readonly type: string; readonly message: string };\n}\n\n// ---------------------------------------------------------------------------\n// AdapterStats bundle\n// ---------------------------------------------------------------------------\n\nexport interface AdapterStats {\n\t/**\n\t * Reactive node for the most-recent call event. Emits `null` initially\n\t * (no calls yet); emits a {@link CallStatsEvent} after each call. Subscribe\n\t * and filter `!= null` if you want a `Node<CallStatsEvent>`.\n\t */\n\treadonly lastCall: Node<CallStatsEvent | null>;\n\t/** Full event log (bounded by `opts.logMax`, default 1000). */\n\treadonly allCalls: ReactiveLogBundle<CallStatsEvent>;\n\t/** Total calls observed since last reset. */\n\treadonly totalCalls: Node<number>;\n\t/** Sum of every input-token class across observed calls. */\n\treadonly totalInputTokens: Node<number>;\n\t/** Sum of every output-token class across observed calls. */\n\treadonly totalOutputTokens: Node<number>;\n\t/** Reset all counters + clear the log. */\n\treset(): void;\n\t/**\n\t * Release the internal keepalive subscriptions on the three counter\n\t * derives (`totalCalls` / `totalInputTokens` / `totalOutputTokens`) so the\n\t * bundle can be GC'd when the caller discards it. Idempotent. Long-lived\n\t * adapter bundles (module-level singletons) can ignore; transient bundles\n\t * (per-request / per-user) should call on teardown.\n\t */\n\tdispose(): void;\n}\n\n// ---------------------------------------------------------------------------\n// observableAdapter\n// ---------------------------------------------------------------------------\n\n/**\n * Wrap any {@link LLMAdapter} with a reactive stats bundle.\n *\n * Implementation (Unit 10 B):\n * - `stats.lastCall` is a `state<CallStatsEvent | null>`.\n * - Counters (`totalCalls` / `totalInputTokens` / `totalOutputTokens`) are\n * **derived views** over `allCalls.entries` — self-maintaining, no manual\n * `.cache + 1 + emit` pattern, visible topology in `describe()`.\n * - `stats.allCalls` is a `reactiveLog<CallStatsEvent>` — bounded, supports\n * `tail(n)` / `slice(start, stop)` for dashboard views.\n * - The wrapped adapter passes DATA through via `adaptInvokeResult`, which\n * uses `onFirstData` internally to guard against re-subscription double-fire\n * and wires `.catch` for Promise-path error recording (Unit 10 A).\n */\nexport function observableAdapter(\n\tinner: LLMAdapter,\n\topts?: { logMax?: number; name?: string },\n): { adapter: LLMAdapter; stats: AdapterStats } {\n\tconst logMax = opts?.logMax ?? 1000;\n\tconst allCalls = reactiveLog<CallStatsEvent>(undefined, {\n\t\tname: opts?.name ? `${opts.name}/stats` : \"adapterStats\",\n\t\tmaxSize: logMax,\n\t});\n\n\tconst lastCall = node<CallStatsEvent | null>([], {\n\t\tname: \"adapterStats/lastCall\",\n\t\tinitial: null,\n\t});\n\n\t// Counters as derived views over the log — self-maintaining (Unit 10 B).\n\t// `initial` seeds them so late subscribers see 0 before any call lands.\n\tconst totalCalls = node<number>(\n\t\t[allCalls.entries],\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 entries = data[0] as readonly CallStatsEvent[];\n\t\t\tactions.emit(entries.length);\n\t\t},\n\t\t{ describeKind: \"derived\", name: \"adapterStats/totalCalls\", initial: 0 },\n\t);\n\tconst totalInputTokens = node<number>(\n\t\t[allCalls.entries],\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 entries = data[0] as readonly CallStatsEvent[];\n\t\t\tactions.emit(entries.reduce((acc, ev) => acc + sumInputTokens(ev.usage), 0));\n\t\t},\n\t\t{ describeKind: \"derived\", name: \"adapterStats/totalInputTokens\", initial: 0 },\n\t);\n\tconst totalOutputTokens = node<number>(\n\t\t[allCalls.entries],\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 entries = data[0] as readonly CallStatsEvent[];\n\t\t\tactions.emit(entries.reduce((acc, ev) => acc + sumOutputTokens(ev.usage), 0));\n\t\t},\n\t\t{ describeKind: \"derived\", name: \"adapterStats/totalOutputTokens\", initial: 0 },\n\t);\n\t// Keepalive — counters track the log whether or not an external subscriber\n\t// is attached, so `.cache` on the counters stays current. Captured as an\n\t// array so `AdapterStats.dispose()` can release them all.\n\tconst unsubKeepalives: Array<() => void> = [\n\t\tkeepalive(totalCalls),\n\t\tkeepalive(totalInputTokens),\n\t\tkeepalive(totalOutputTokens),\n\t];\n\n\tconst record = (ev: CallStatsEvent): void => {\n\t\tallCalls.append(ev);\n\t\tlastCall.emit(ev);\n\t};\n\n\tconst reset = (): void => {\n\t\tallCalls.clear();\n\t\tlastCall.emit(null);\n\t};\n\n\tconst wrap = adapterWrapper(inner, {\n\t\tinvoke(messages, invokeOpts) {\n\t\t\tconst startNs = monotonicNs();\n\t\t\tconst startWallClockNs = wallClockNs();\n\t\t\tconst model = inner.model ?? invokeOpts?.model ?? \"\";\n\t\t\tconst recordResp = (resp: LLMResponse): LLMResponse => {\n\t\t\t\trecord(\n\t\t\t\t\tbuildCallStats({\n\t\t\t\t\t\tprovider: inner.provider,\n\t\t\t\t\t\tmodel: inner.model ?? invokeOpts?.model ?? resp.model ?? \"\",\n\t\t\t\t\t\ttier: invokeOpts?.tier ?? resp.tier,\n\t\t\t\t\t\tusage: resp.usage ?? emptyUsageStub(),\n\t\t\t\t\t\tstartNs,\n\t\t\t\t\t\tstartWallClockNs,\n\t\t\t\t\t\tmethod: \"invoke\",\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn resp;\n\t\t\t};\n\t\t\tconst recordErr = (err: unknown): void => {\n\t\t\t\tconst e = err as Error | undefined;\n\t\t\t\trecord(\n\t\t\t\t\tbuildCallStats({\n\t\t\t\t\t\tprovider: inner.provider,\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttier: invokeOpts?.tier,\n\t\t\t\t\t\tusage: emptyUsageStub(),\n\t\t\t\t\t\tstartNs,\n\t\t\t\t\t\tstartWallClockNs,\n\t\t\t\t\t\tmethod: \"invoke\",\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\ttype: e?.name ?? \"Error\",\n\t\t\t\t\t\t\tmessage: e?.message ?? String(err),\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\treturn adaptInvokeResult(inner.invoke(messages, invokeOpts), {\n\t\t\t\tonResp: recordResp,\n\t\t\t\tonError: recordErr,\n\t\t\t\tname: \"adapterStats/invokeTap\",\n\t\t\t});\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts) {\n\t\t\tconst startNs = monotonicNs();\n\t\t\tconst startWallClockNs = wallClockNs();\n\t\t\tconst model = inner.model ?? invokeOpts?.model ?? \"\";\n\t\t\tlet finalUsage: TokenUsage | undefined;\n\t\t\ttry {\n\t\t\t\tfor await (const delta of inner.stream(messages, invokeOpts)) {\n\t\t\t\t\tif (delta.type === \"usage\") finalUsage = delta.usage;\n\t\t\t\t\tyield delta;\n\t\t\t\t}\n\t\t\t\trecord(\n\t\t\t\t\tbuildCallStats({\n\t\t\t\t\t\tprovider: inner.provider,\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttier: invokeOpts?.tier,\n\t\t\t\t\t\tusage: finalUsage ?? emptyUsageStub(),\n\t\t\t\t\t\tstartNs,\n\t\t\t\t\t\tstartWallClockNs,\n\t\t\t\t\t\tmethod: \"stream\",\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} catch (err) {\n\t\t\t\tconst e = err as Error | undefined;\n\t\t\t\trecord(\n\t\t\t\t\tbuildCallStats({\n\t\t\t\t\t\tprovider: inner.provider,\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\ttier: invokeOpts?.tier,\n\t\t\t\t\t\tusage: finalUsage ?? emptyUsageStub(),\n\t\t\t\t\t\tstartNs,\n\t\t\t\t\t\tstartWallClockNs,\n\t\t\t\t\t\tmethod: \"stream\",\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\ttype: e?.name ?? \"Error\",\n\t\t\t\t\t\t\tmessage: e?.message ?? String(err),\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\t});\n\n\twithLayer(wrap, \"observableAdapter\", inner);\n\n\tlet disposed = false;\n\tconst dispose = (): void => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tfor (const fn of unsubKeepalives) fn();\n\t\tunsubKeepalives.length = 0;\n\t};\n\n\tconst stats: AdapterStats = {\n\t\tlastCall,\n\t\tallCalls,\n\t\ttotalCalls,\n\t\ttotalInputTokens,\n\t\ttotalOutputTokens,\n\t\treset,\n\t\tdispose,\n\t};\n\n\treturn { adapter: wrap, stats };\n}\n\nexport type { ChatMessage, LLMAdapter, LLMInvokeOptions, LLMResponse, StreamDelta, TokenUsage };\n","/**\n * Core types for LLM adapters (roadmap §9.3d).\n *\n * The library defines the shape of:\n * - Token usage (raw, disaggregated; user decides how to combine)\n * - Responses and streaming deltas\n * - The `LLMAdapter` protocol (reactive-friendly via `NodeInput`)\n * - Chat, tool, and invocation option shapes\n *\n * It ships **zero model data**. Pricing and capability registries are\n * user-populated (see `pricing.ts` and `capabilities.ts`).\n */\n\nimport type { Node } from \"@graphrefly/pure-ts/core\";\nimport type { NodeInput } from \"@graphrefly/pure-ts/extra\";\n\n// ---------------------------------------------------------------------------\n// Token usage — raw, disaggregated, extensible\n// ---------------------------------------------------------------------------\n\n/**\n * Input token classes.\n *\n * Every provider's native usage object maps into this shape without loss.\n * All fields except `regular` are optional — providers that don't expose\n * the class simply leave it undefined.\n */\nexport interface InputTokens {\n\t/** Uncached regular input tokens (cache miss or never-cached). */\n\tregular: number;\n\t/** Read from prompt cache (all TTLs — providers don't split reads by TTL today). */\n\tcacheRead?: number;\n\t/** Written to cache with 5-min TTL (Anthropic `ephemeral_5m_input_tokens`). */\n\tcacheWrite5m?: number;\n\t/** Written to cache with 1-hour TTL (Anthropic `ephemeral_1h_input_tokens`). */\n\tcacheWrite1h?: number;\n\t/** Written to cache with other/unspecified TTL (Gemini explicit caches). */\n\tcacheWriteOther?: number;\n\t/** Audio input tokens (OpenAI realtime, Gemini audio). */\n\taudio?: number;\n\t/** Image input tokens (Gemini per-modality). */\n\timage?: number;\n\t/** Video input tokens (Gemini per-modality). */\n\tvideo?: number;\n\t/** Tool-use result tokens fed back to the model (Gemini `toolUsePromptTokenCount`). */\n\ttoolUse?: number;\n\t/** Provider-specific classes not covered above. Open-ended by design. */\n\textensions?: Record<string, number>;\n}\n\n/** Output token classes. */\nexport interface OutputTokens {\n\t/** Regular generated output (non-reasoning, non-audio). */\n\tregular: number;\n\t/** Reasoning / thinking tokens (OpenAI o-series, Gemini thoughts, Grok reasoning). */\n\treasoning?: number;\n\t/** Audio output tokens. */\n\taudio?: number;\n\t/** Predicted-output tokens accepted (OpenAI predictions API). */\n\tpredictionAccepted?: number;\n\t/** Predicted-output tokens rejected (still billed at output rate). */\n\tpredictionRejected?: number;\n\textensions?: Record<string, number>;\n}\n\n/** Per-call token usage in canonical shape. No pricing, no interpretation. */\nexport interface TokenUsage {\n\tinput: InputTokens;\n\toutput: OutputTokens;\n\t/**\n\t * Per-call non-token costs (web-search requests, tool invocations, cache\n\t * storage-hours, etc.). Units are domain-specific — pricing functions\n\t * interpret them via `ModelPricing.auxiliary`.\n\t */\n\tauxiliary?: Record<string, number>;\n\t/**\n\t * Raw provider usage object, unmodified. Escape hatch for anything the\n\t * canonical shape doesn't model.\n\t */\n\traw?: unknown;\n}\n\n/** Sum of every input-token class. Helper for pricing + budget gating. */\nexport function sumInputTokens(u: TokenUsage): number {\n\tconst i = u.input;\n\tconst base =\n\t\ti.regular +\n\t\t(i.cacheRead ?? 0) +\n\t\t(i.cacheWrite5m ?? 0) +\n\t\t(i.cacheWrite1h ?? 0) +\n\t\t(i.cacheWriteOther ?? 0) +\n\t\t(i.audio ?? 0) +\n\t\t(i.image ?? 0) +\n\t\t(i.video ?? 0) +\n\t\t(i.toolUse ?? 0);\n\tif (!i.extensions) return base;\n\tlet ext = 0;\n\tfor (const v of Object.values(i.extensions)) ext += v;\n\treturn base + ext;\n}\n\n/** Sum of every output-token class. */\nexport function sumOutputTokens(u: TokenUsage): number {\n\tconst o = u.output;\n\tconst base =\n\t\to.regular +\n\t\t(o.reasoning ?? 0) +\n\t\t(o.audio ?? 0) +\n\t\t(o.predictionAccepted ?? 0) +\n\t\t(o.predictionRejected ?? 0);\n\tif (!o.extensions) return base;\n\tlet ext = 0;\n\tfor (const v of Object.values(o.extensions)) ext += v;\n\treturn base + ext;\n}\n\n/** Empty `TokenUsage` — useful as a default / starting point. */\nexport function emptyUsage(): TokenUsage {\n\treturn { input: { regular: 0 }, output: { regular: 0 } };\n}\n\n// ---------------------------------------------------------------------------\n// Chat message / tool types (single source of truth for the AI layer)\n// ---------------------------------------------------------------------------\n\n/** A single chat message in a conversation. */\nexport type ChatMessage = {\n\treadonly role: \"system\" | \"user\" | \"assistant\" | \"tool\";\n\treadonly content: string;\n\treadonly name?: string;\n\treadonly toolCallId?: string;\n\treadonly toolCalls?: readonly ToolCall[];\n\treadonly metadata?: Record<string, unknown>;\n};\n\n/** A tool invocation request from an LLM. */\nexport type ToolCall = {\n\treadonly id: string;\n\treadonly name: string;\n\treadonly arguments: Record<string, unknown>;\n};\n\n/** A tool definition for LLM consumption. */\nexport type ToolDefinition = {\n\treadonly name: string;\n\treadonly description: string;\n\treadonly parameters: Record<string, unknown>; // JSON Schema\n\t/**\n\t * Handler invoked when the LLM requests this tool.\n\t *\n\t * The optional `opts.signal` fires when the reactive surface that owns\n\t * this invocation is torn down (e.g. the agent's `switchMap` over\n\t * `toolCalls` superseded with a fresh batch, the agent was aborted, or\n\t * the parent graph destroyed). Signal-aware handlers should thread it\n\t * into `fetch(url, {signal})`, child-process kill, DB cancel, etc., so\n\t * in-flight side effects actually stop. Handlers that ignore the\n\t * signal still work — but their work continues to completion regardless\n\t * of supersede.\n\t */\n\treadonly handler: (\n\t\targs: Record<string, unknown>,\n\t\topts?: { signal?: AbortSignal },\n\t) => NodeInput<unknown>;\n\t/**\n\t * V0 version of the backing node at tool-definition-creation time.\n\t * Snapshot — re-create the tool definition to refresh.\n\t */\n\treadonly version?: { id: string; version: number };\n};\n\n// ---------------------------------------------------------------------------\n// Response / streaming\n// ---------------------------------------------------------------------------\n\n/** The response from an LLM invocation. */\nexport interface LLMResponse {\n\treadonly content: string;\n\treadonly toolCalls?: readonly ToolCall[];\n\t/**\n\t * Token usage. Optional — provider adapters should always populate it, but\n\t * test mocks and adapter middlewares that synthesize responses can omit it.\n\t * Downstream consumers that compute cost should default to {@link emptyUsage}.\n\t */\n\treadonly usage?: TokenUsage;\n\treadonly finishReason?: string;\n\treadonly latencyMs?: number;\n\treadonly model?: string;\n\treadonly provider?: string;\n\t/** Service tier the call was served with (standard / batch / flex / priority). */\n\treadonly tier?: string;\n\treadonly metadata?: Record<string, unknown>;\n}\n\n/**\n * Adapter-facing incremental stream event.\n *\n * Provider adapters emit these; higher-level surfaces (`streamingPromptNode`,\n * `agentLoop`) assemble them into consumer-facing `StreamChunk` with their own\n * `source`/`accumulated`/`index` context.\n *\n * **Shape rationale — why object tagged-union vs. the framework `[TYPE, data]`\n * tuple?** `StreamDelta` is an *application-layer event payload* that flows\n * inside a single framework `DATA` message, one abstraction level above the\n * reactive protocol. The framework's `[Type, Data?]` tuple (DIRTY / DATA /\n * RESOLVED / COMPLETE / ERROR) is the protocol message form delivered through\n * `subscribe`. Using the protocol form here would force us to invent new\n * framework-level symbols (`TOKEN`, `USAGE`, etc.) that leak into user code,\n * and TypeScript discriminated-union exhaustiveness works much better with\n * objects than tuples. Object-tagged unions match the idiomatic JS/TS\n * convention for discriminated events (Redux actions, DOM events).\n */\nexport type StreamDelta =\n\t| { readonly type: \"token\"; readonly delta: string }\n\t| {\n\t\t\treadonly type: \"tool-call-delta\";\n\t\t\treadonly delta: {\n\t\t\t\treadonly id?: string;\n\t\t\t\treadonly name?: string;\n\t\t\t\treadonly argumentsDelta?: string;\n\t\t\t};\n\t }\n\t| { readonly type: \"thinking\"; readonly delta: string }\n\t| { readonly type: \"usage\"; readonly usage: TokenUsage }\n\t| { readonly type: \"finish\"; readonly reason: string };\n\n// ---------------------------------------------------------------------------\n// Invocation options\n// ---------------------------------------------------------------------------\n\n/** Options passed to `invoke()` / `stream()`. */\nexport interface LLMInvokeOptions {\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\t/** Budget for reasoning/thinking tokens, if the model supports it. */\n\tmaxReasoningTokens?: number;\n\ttools?: readonly ToolDefinition[];\n\tsystemPrompt?: string;\n\t/** Hint the adapter to cache the prompt. TTL values depend on provider. */\n\tcacheHint?: { ttl?: \"5m\" | \"1h\" | string; minTokens?: number };\n\t/** Service tier: \"standard\" | \"batch\" | \"flex\" | \"priority\" | provider-custom. */\n\ttier?: string;\n\tsignal?: AbortSignal;\n\t/**\n\t * Provider-specific passthrough — merged into the native request body.\n\t * Escape hatch for features not yet in the canonical options.\n\t */\n\tproviderExtras?: Record<string, unknown>;\n\t/**\n\t * Open-ended per-call context threaded to cache / fallback key functions.\n\t * Callers who want to shard caches by tenant, session, feature flag, or\n\t * any other dimension populate this and supply a custom `keyFn` that\n\t * incorporates it. Not sent to providers — stripped from canonical key\n\t * hashing when no custom `keyFn` is supplied. Type is `unknown` to avoid\n\t * prescribing a shape; callers pick their own.\n\t */\n\tkeyContext?: unknown;\n}\n\n// ---------------------------------------------------------------------------\n// LLMAdapter protocol\n// ---------------------------------------------------------------------------\n\n/**\n * Provider-agnostic LLM adapter (spec §5.10 compliant).\n *\n * - `invoke()` returns a `NodeInput<LLMResponse>` — the caller bridges to\n * reactive via `fromAny(...)`. Adapter implementations may return a\n * Promise (simplest), a Node (reactive), or a plain value (testing).\n * - `stream()` returns `AsyncIterable<StreamDelta>` — the terminal delta of\n * type `\"usage\"` carries the final `TokenUsage` for the streamed call.\n */\nexport interface LLMAdapter {\n\treadonly provider: string;\n\treadonly model?: string;\n\tinvoke(messages: readonly ChatMessage[], opts?: LLMInvokeOptions): NodeInput<LLMResponse>;\n\tstream(messages: readonly ChatMessage[], opts?: LLMInvokeOptions): AsyncIterable<StreamDelta>;\n\t/** Optional capability lookup; typically delegates to a `CapabilitiesRegistry`. */\n\tcapabilities?(model?: string): import(\"./capabilities.js\").ModelCapabilities | undefined;\n\t/**\n\t * DS-14.5 / AB-1 — honoring `opts.signal: AbortSignal` end-to-end is a\n\t * **hard adapter contract**, not an opt-in capability. Every adapter MUST\n\t * thread `opts.signal` into its underlying I/O (`fetch` request,\n\t * child-process kill, DB cancel) so a mid-call abort cancels the work and\n\t * surfaces as a rejection / thrown error. The prior optional\n\t * `abortCapable?: boolean` flag (Lock 3.C / QA D3) was removed pre-1.0:\n\t * the capability-flag escape hatch silently permitted token burn-through\n\t * past `valve`-close / `switchMap`-supersede / budget exhaustion. There is\n\t * no longer a flag to set and no dev-mode warning — abort just works.\n\t */\n}\n\n/** Discriminator for downstream type guards. */\nexport function isLLMAdapter(x: unknown): x is LLMAdapter {\n\tif (x == null || typeof x !== \"object\") return false;\n\tconst a = x as Partial<LLMAdapter>;\n\treturn (\n\t\ttypeof a.provider === \"string\" &&\n\t\ttypeof a.invoke === \"function\" &&\n\t\ttypeof a.stream === \"function\"\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// Public re-export surface\n// ---------------------------------------------------------------------------\n\nexport type { Node, NodeInput };\n","/**\n * Pluggable pricing for LLM adapters.\n *\n * The library ships the **shape** (types + computation helpers + registry\n * factory) and **zero model data**. Users populate a `PricingRegistry` with\n * the prices for the models they use — either by hand, from a curated table,\n * or by importing a third-party dataset (litellm JSON, etc.).\n *\n * Pricing is a pure function of raw `TokenUsage`. The library does not\n * know current prices, regional rates, tier thresholds, or promotional\n * discounts — those are all user domain.\n */\n\nimport type { TokenUsage } from \"./types.js\";\nimport { sumInputTokens } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Rate shape\n// ---------------------------------------------------------------------------\n\n/**\n * A rate per 1M tokens. Supports threshold-based tiering (Anthropic\n * long-context >200K, Gemini >200K) via optional `thresholdTokens` +\n * `pricePerMillionAbove`.\n *\n * `total input tokens` (sum of every input class) is the axis the threshold\n * applies to — matches how Anthropic and Gemini measure it.\n */\nexport interface TieredRate {\n\tpricePerMillion: number;\n\tthresholdTokens?: number;\n\tpricePerMillionAbove?: number;\n}\n\n/** Shorthand: a plain `number` stands for `{pricePerMillion: n}`. */\nexport type Rate = TieredRate | number;\n\nfunction rateAt(rate: Rate | undefined, totalInput: number): number {\n\tif (rate == null) return 0;\n\tif (typeof rate === \"number\") return rate;\n\tif (\n\t\trate.thresholdTokens != null &&\n\t\trate.pricePerMillionAbove != null &&\n\t\ttotalInput > rate.thresholdTokens\n\t) {\n\t\treturn rate.pricePerMillionAbove;\n\t}\n\treturn rate.pricePerMillion;\n}\n\n// ---------------------------------------------------------------------------\n// ModelPricing\n// ---------------------------------------------------------------------------\n\n/** USD-per-1M rates per token class. All fields optional. */\nexport interface ModelPricing {\n\tinput?: {\n\t\tregular?: Rate;\n\t\tcacheRead?: Rate;\n\t\tcacheWrite5m?: Rate;\n\t\tcacheWrite1h?: Rate;\n\t\tcacheWriteOther?: Rate;\n\t\taudio?: Rate;\n\t\timage?: Rate;\n\t\tvideo?: Rate;\n\t\ttoolUse?: Rate;\n\t\textensions?: Record<string, Rate>;\n\t};\n\toutput?: {\n\t\tregular?: Rate;\n\t\treasoning?: Rate;\n\t\taudio?: Rate;\n\t\tpredictionAccepted?: Rate;\n\t\tpredictionRejected?: Rate;\n\t\textensions?: Record<string, Rate>;\n\t};\n\t/**\n\t * Per-unit costs for non-token axes. Values are USD per unit; units\n\t * match `TokenUsage.auxiliary` keys (e.g. `webSearchRequests`, `cacheStorageHours`).\n\t */\n\tauxiliary?: Record<string, number>;\n\t/**\n\t * Service-tier multipliers. Applied to the summed per-class price.\n\t * E.g. `{ batch: 0.5, flex: 0.5, priority: 1.25 }`. Default (no tier or\n\t * tier not present in the map): multiplier = 1.\n\t */\n\ttierMultipliers?: Record<string, number>;\n\t/** Currency code (ISO 4217). Defaults to \"USD\" when constructed via helpers. */\n\tcurrency: string;\n}\n\n// ---------------------------------------------------------------------------\n// Price breakdown\n// ---------------------------------------------------------------------------\n\n/** Result of computing a price from usage + pricing. */\nexport interface PriceBreakdown {\n\t/** Total charge in `currency`. */\n\ttotal: number;\n\tcurrency: string;\n\t/**\n\t * Optional per-class subtotals. Keys are dot-separated paths like\n\t * `\"input.regular\"`, `\"output.reasoning\"`, `\"auxiliary.webSearchRequests\"`.\n\t */\n\tbreakdown?: Record<string, number>;\n}\n\n/** Zero-charge breakdown — returned when no pricing is available for a model. */\nexport function zeroPrice(currency = \"USD\"): PriceBreakdown {\n\treturn { total: 0, currency };\n}\n\n// ---------------------------------------------------------------------------\n// computePrice — the math\n// ---------------------------------------------------------------------------\n\n/**\n * Compute price from a usage object + model pricing.\n *\n * - Tier-threshold math uses `sumInputTokens(usage)` as the axis.\n * - Service tier (`opts.tier`) multiplies the final total via `tierMultipliers`.\n * - Each token class is priced independently using the matching `Rate` lookup.\n * - `breakdown` is populated when `opts.withBreakdown = true` (default false\n * to keep hot-path allocations low).\n */\nexport function computePrice(\n\tusage: TokenUsage,\n\tpricing: ModelPricing,\n\topts?: { tier?: string; withBreakdown?: boolean },\n): PriceBreakdown {\n\tconst totalInput = sumInputTokens(usage);\n\tconst currency = pricing.currency ?? \"USD\";\n\tconst withBreakdown = opts?.withBreakdown === true;\n\tconst breakdown: Record<string, number> = withBreakdown ? {} : (null as never);\n\n\tlet total = 0;\n\n\tconst addLine = (key: string, tokens: number, rate: Rate | undefined): void => {\n\t\tif (!tokens || rate == null) return;\n\t\tconst rateUsd = rateAt(rate, totalInput);\n\t\tconst line = (tokens * rateUsd) / 1_000_000;\n\t\ttotal += line;\n\t\tif (withBreakdown) breakdown[key] = (breakdown[key] ?? 0) + line;\n\t};\n\n\t// Input classes\n\tconst i = usage.input;\n\tconst pi = pricing.input;\n\tif (pi) {\n\t\taddLine(\"input.regular\", i.regular, pi.regular);\n\t\taddLine(\"input.cacheRead\", i.cacheRead ?? 0, pi.cacheRead);\n\t\taddLine(\"input.cacheWrite5m\", i.cacheWrite5m ?? 0, pi.cacheWrite5m);\n\t\taddLine(\"input.cacheWrite1h\", i.cacheWrite1h ?? 0, pi.cacheWrite1h);\n\t\taddLine(\"input.cacheWriteOther\", i.cacheWriteOther ?? 0, pi.cacheWriteOther);\n\t\taddLine(\"input.audio\", i.audio ?? 0, pi.audio);\n\t\taddLine(\"input.image\", i.image ?? 0, pi.image);\n\t\taddLine(\"input.video\", i.video ?? 0, pi.video);\n\t\taddLine(\"input.toolUse\", i.toolUse ?? 0, pi.toolUse);\n\t\tif (i.extensions && pi.extensions) {\n\t\t\tfor (const [k, v] of Object.entries(i.extensions)) {\n\t\t\t\taddLine(`input.ext.${k}`, v, pi.extensions[k]);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Output classes\n\tconst o = usage.output;\n\tconst po = pricing.output;\n\tif (po) {\n\t\taddLine(\"output.regular\", o.regular, po.regular);\n\t\taddLine(\"output.reasoning\", o.reasoning ?? 0, po.reasoning);\n\t\taddLine(\"output.audio\", o.audio ?? 0, po.audio);\n\t\taddLine(\"output.predictionAccepted\", o.predictionAccepted ?? 0, po.predictionAccepted);\n\t\taddLine(\"output.predictionRejected\", o.predictionRejected ?? 0, po.predictionRejected);\n\t\tif (o.extensions && po.extensions) {\n\t\t\tfor (const [k, v] of Object.entries(o.extensions)) {\n\t\t\t\taddLine(`output.ext.${k}`, v, po.extensions[k]);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Service-tier multiplier applies to token costs only. Auxiliary costs\n\t// (per-request web-search fees, cache storage-hours, etc.) are typically\n\t// priced flat regardless of tier — e.g., Anthropic batch discount applies\n\t// to input/output tokens but NOT to web_search_requests. Apply the\n\t// multiplier to the token total before adding auxiliary lines.\n\tconst tier = opts?.tier;\n\tif (tier && pricing.tierMultipliers) {\n\t\tconst mult = pricing.tierMultipliers[tier];\n\t\tif (mult != null) {\n\t\t\ttotal *= mult;\n\t\t\tif (withBreakdown) {\n\t\t\t\tfor (const k of Object.keys(breakdown)) breakdown[k] *= mult;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Auxiliary (per-unit, not per-million; not tier-multiplied)\n\tconst aux = usage.auxiliary;\n\tconst paux = pricing.auxiliary;\n\tif (aux && paux) {\n\t\tfor (const [k, units] of Object.entries(aux)) {\n\t\t\tconst rate = paux[k];\n\t\t\tif (rate == null || !units) continue;\n\t\t\tconst line = units * rate;\n\t\t\ttotal += line;\n\t\t\tif (withBreakdown) breakdown[`auxiliary.${k}`] = line;\n\t\t}\n\t}\n\n\treturn withBreakdown ? { total, currency, breakdown } : { total, currency };\n}\n\n// ---------------------------------------------------------------------------\n// PricingFn\n// ---------------------------------------------------------------------------\n\n/** Pure function: given usage + call context, produce a price. */\nexport type PricingFn = (\n\tusage: TokenUsage,\n\tctx: { model: string; provider: string; tier?: string; withBreakdown?: boolean },\n) => PriceBreakdown;\n\n// ---------------------------------------------------------------------------\n// PricingRegistry\n// ---------------------------------------------------------------------------\n\n/**\n * A keyed store of `ModelPricing`. Users populate it at app startup.\n * The library ships the factory and zero data.\n *\n * Keys are `(provider, model)` pairs. Lookup attempts exact match first,\n * then longest-prefix match on model (e.g. `\"claude-sonnet-4-6\"` matches a\n * stored `\"claude-sonnet-4-6\"` entry when looking up\n * `\"claude-sonnet-4-6-20260401\"`).\n *\n * **Prefix-match footgun:** a registered `\"gemini-1\"` will also match a\n * lookup for `\"gemini-1.5-pro\"` (since `\"gemini-1.5-pro\".startsWith(\"gemini-1\")`\n * is true). Longest-match tie-breaking mitigates most cases, but when\n * registering a short family-prefix alongside versioned descendants, make sure\n * the versioned entry is present — otherwise the family prefix wins. Best\n * practice: register exact versioned model ids; use short family aliases\n * sparingly and only when all version variants share one pricing schedule.\n */\nexport interface PricingRegistry {\n\tlookup(provider: string, model: string): ModelPricing | undefined;\n\tregister(provider: string, model: string, pricing: ModelPricing): void;\n\t/** Remove a model's entry; returns `true` if it existed. */\n\tremove(provider: string, model: string): boolean;\n\t/** Enumerate all entries (for debugging / dump). */\n\tentries(): IterableIterator<[string, string, ModelPricing]>;\n}\n\nfunction registryKey(provider: string, model: string): string {\n\treturn `${provider}::${model}`;\n}\n\n/** Create a fresh `PricingRegistry`. Optionally seed with entries. */\nexport function createPricingRegistry(\n\tinitial?: ReadonlyArray<readonly [provider: string, model: string, pricing: ModelPricing]>,\n): PricingRegistry {\n\tconst map = new Map<string, { provider: string; model: string; pricing: ModelPricing }>();\n\tconst indexByProvider = new Map<string, Set<string>>();\n\n\tconst register = (provider: string, model: string, pricing: ModelPricing): void => {\n\t\tmap.set(registryKey(provider, model), { provider, model, pricing });\n\t\tlet models = indexByProvider.get(provider);\n\t\tif (!models) {\n\t\t\tmodels = new Set();\n\t\t\tindexByProvider.set(provider, models);\n\t\t}\n\t\tmodels.add(model);\n\t};\n\n\tif (initial) {\n\t\tfor (const [p, m, pricing] of initial) register(p, m, pricing);\n\t}\n\n\treturn {\n\t\tregister,\n\t\tlookup(provider, model) {\n\t\t\tconst exact = map.get(registryKey(provider, model));\n\t\t\tif (exact) return exact.pricing;\n\t\t\t// Prefix fallback within provider.\n\t\t\tconst models = indexByProvider.get(provider);\n\t\t\tif (!models) return undefined;\n\t\t\t// Pick the longest prefix match for stability.\n\t\t\tlet best: { key: string; pricing: ModelPricing } | undefined;\n\t\t\tfor (const candidate of models) {\n\t\t\t\tif (model.startsWith(candidate)) {\n\t\t\t\t\tif (!best || candidate.length > best.key.length) {\n\t\t\t\t\t\tconst entry = map.get(registryKey(provider, candidate));\n\t\t\t\t\t\tif (entry) best = { key: candidate, pricing: entry.pricing };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn best?.pricing;\n\t\t},\n\t\tremove(provider, model) {\n\t\t\tconst existed = map.delete(registryKey(provider, model));\n\t\t\tif (existed) {\n\t\t\t\tconst models = indexByProvider.get(provider);\n\t\t\t\tmodels?.delete(model);\n\t\t\t\tif (models && models.size === 0) indexByProvider.delete(provider);\n\t\t\t}\n\t\t\treturn existed;\n\t\t},\n\t\tentries(): IterableIterator<[string, string, ModelPricing]> {\n\t\t\tconst iter = map.values();\n\t\t\treturn (function* () {\n\t\t\t\tfor (const { provider, model, pricing } of iter) {\n\t\t\t\t\tyield [provider, model, pricing];\n\t\t\t\t}\n\t\t\t})();\n\t\t},\n\t};\n}\n\n/**\n * Build a `PricingFn` from a `PricingRegistry`. If no entry matches, returns\n * `{ total: 0, currency: \"USD\" }` (never throws). Callers who need \"unknown\n * model\" failures can compose their own `PricingFn`.\n */\nexport function registryPricing(registry: PricingRegistry, defaultCurrency = \"USD\"): PricingFn {\n\treturn (usage, ctx) => {\n\t\tconst pricing = registry.lookup(ctx.provider, ctx.model);\n\t\tif (!pricing) return zeroPrice(defaultCurrency);\n\t\treturn computePrice(usage, pricing, { tier: ctx.tier, withBreakdown: ctx.withBreakdown });\n\t};\n}\n\n/** Compose multiple `PricingFn`s — first non-zero wins. Useful for registry layering. */\nexport function composePricing(...fns: readonly PricingFn[]): PricingFn {\n\treturn (usage, ctx) => {\n\t\tfor (const fn of fns) {\n\t\t\tconst p = fn(usage, ctx);\n\t\t\tif (p.total !== 0) return p;\n\t\t}\n\t\treturn fns.length > 0 ? fns[0](usage, ctx) : zeroPrice();\n\t};\n}\n\n/**\n * Convenience: compute a {@link PriceBreakdown} directly from a\n * {@link import(\"./capabilities.js\").ModelCapabilities} object + usage.\n *\n * When callers look up capabilities themselves (via\n * `capabilitiesRegistry.lookup(...)` or `adapter.capabilities?.(model)`),\n * this helper skips the pricing-registry round-trip and computes the price\n * from `capabilities.pricing` directly.\n *\n * Returns `zeroPrice()` when `capabilities.pricing` is undefined — never throws.\n *\n * @param capabilities - Model capabilities object (`capabilities.pricing` may be absent).\n * @param usage - Per-call usage to price.\n * @param opts - Pass-through to {@link computePrice}.\n *\n * @example\n * ```ts\n * const cap = registry.lookup(\"anthropic\", \"claude-sonnet-4-6\");\n * const price = pricingFor(cap, resp.usage, { tier: \"batch\", withBreakdown: true });\n * ```\n *\n * @category ai\n */\nexport function pricingFor(\n\tcapabilities: import(\"./capabilities.js\").ModelCapabilities | undefined,\n\tusage: TokenUsage,\n\topts?: { tier?: string; withBreakdown?: boolean },\n): PriceBreakdown {\n\tif (!capabilities?.pricing) return zeroPrice();\n\treturn computePrice(usage, capabilities.pricing, opts);\n}\n","/**\n * `withBreaker` — circuit-breaker middleware for LLM adapters.\n *\n * Reuses the library's existing `circuitBreaker` primitive from\n * `extra/resilience.ts`. When the breaker is open, calls throw\n * `CircuitOpenError` instead of hitting the provider.\n */\n\nimport { fromAny } from \"@graphrefly/pure-ts/extra\";\nimport { firstValueFrom } from \"../../../../base/sources/settled.js\";\nimport {\n\ttype CircuitBreaker,\n\ttype CircuitBreakerOptions,\n\tCircuitOpenError,\n\tcircuitBreaker,\n} from \"../../../../utils/resilience/index.js\";\nimport { adapterWrapper, withLayer } from \"../_internal/wrappers.js\";\nimport type { LLMAdapter, LLMResponse, StreamDelta } from \"../core/types.js\";\n\nexport interface WithBreakerOptions extends CircuitBreakerOptions {\n\t/**\n\t * Optional external breaker — pass a shared instance to wire the same\n\t * breaker across multiple adapters (e.g. all tiers of a `cascadingLlmAdapter`).\n\t */\n\tbreaker?: CircuitBreaker;\n}\n\nexport function withLLMBreaker(\n\tinner: LLMAdapter,\n\topts: WithBreakerOptions = {},\n): { adapter: LLMAdapter; breaker: CircuitBreaker } {\n\tconst breaker = opts.breaker ?? circuitBreaker(opts);\n\n\tconst adapter: LLMAdapter = adapterWrapper(inner, {\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tif (!breaker.canExecute()) throw new CircuitOpenError();\n\t\t\ttry {\n\t\t\t\tconst resp = await firstValueFrom(fromAny(inner.invoke(messages, invokeOpts)));\n\t\t\t\tbreaker.recordSuccess();\n\t\t\t\treturn resp;\n\t\t\t} catch (err) {\n\t\t\t\tbreaker.recordFailure(err);\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tif (!breaker.canExecute()) throw new CircuitOpenError();\n\t\t\ttry {\n\t\t\t\tfor await (const d of inner.stream(messages, invokeOpts)) yield d;\n\t\t\t\tbreaker.recordSuccess();\n\t\t\t} catch (err) {\n\t\t\t\tbreaker.recordFailure(err);\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\t});\n\twithLayer(adapter, \"withLLMBreaker\", inner);\n\n\treturn { adapter, breaker };\n}\n\nexport { CircuitOpenError };\n","/**\n * `withBudgetGate` — cap an adapter by calls / tokens / USD.\n *\n * Totals are an O(1)-per-event running accumulator (a `state<BudgetTotals>`\n * updated imperatively inside `record()`), not a derived reduce over the\n * full log — avoids the quadratic cost at sustained traffic while preserving\n * the reactive surface. The full log is still exposed via the bundle for\n * dashboards / auditors.\n *\n * Budgets are enforced imperatively at `invoke()` / `stream()` entry — the\n * running totals + `isOpen.cache` are read; if closed, the call rejects /\n * throws `BudgetExhaustedError` without hitting the wrapped adapter. On\n * success, the call's usage is appended to the log AND debits the running\n * totals in a single synchronous update.\n *\n * Wave A Unit 11 Q4: rejected-Promise path now wires `.catch` (via\n * `adaptInvokeResult.onError`) so failed invoke calls record a CallStatsEvent\n * with `error` populated. Prior code silently dropped rejection from the\n * `totals` / `log` surface.\n */\n\nimport { DATA, monotonicNs, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { keepalive, type ReactiveLogBundle, reactiveLog } from \"@graphrefly/pure-ts/extra\";\nimport {\n\tadapterWrapper,\n\tadaptInvokeResult,\n\tbuildCallStats,\n\temptyUsageStub,\n\twithLayer,\n} from \"../_internal/wrappers.js\";\nimport type { CallStatsEvent } from \"../core/observable.js\";\nimport type { PricingFn } from \"../core/pricing.js\";\nimport type {\n\tChatMessage,\n\tLLMAdapter,\n\tLLMInvokeOptions,\n\tLLMResponse,\n\tStreamDelta,\n\tTokenUsage,\n} from \"../core/types.js\";\nimport { sumInputTokens, sumOutputTokens } from \"../core/types.js\";\n\nexport class BudgetExhaustedError extends Error {\n\toverride name = \"BudgetExhaustedError\";\n\tconstructor(\n\t\tpublic readonly which: string,\n\t\tpublic readonly limit: number,\n\t\tpublic readonly observed: number,\n\t) {\n\t\tsuper(`Budget exhausted: ${which} (limit=${limit}, observed=${observed})`);\n\t}\n}\n\nexport interface BudgetCaps {\n\tcalls?: number;\n\tinputTokens?: number;\n\toutputTokens?: number;\n\tusd?: number;\n}\n\nexport interface BudgetTotals {\n\tcalls: number;\n\tinputTokens: number;\n\toutputTokens: number;\n\tusd: number;\n}\n\nexport interface LLMBudgetGateBundle {\n\ttotals: Node<BudgetTotals>;\n\tisOpen: Node<boolean>;\n\tlog: ReactiveLogBundle<CallStatsEvent>;\n\treset(): void;\n\t/**\n\t * QA D2 (Phase 13.6.B QA pass): release every long-lived\n\t * subscription this gate holds — `keepalive(isOpen)`, the optional\n\t * `onExhausted` subscription, and the Lock 3.C abort fan-out\n\t * subscription on `isOpen`. Aborts any in-flight controllers as a\n\t * defensive last gasp so callers waiting on a soon-to-be-disposed\n\t * adapter don't hang.\n\t *\n\t * Idempotent: subsequent calls are no-ops. After `dispose()` the\n\t * adapter wrapper continues to wrap `inner.invoke` / `inner.stream`\n\t * but the budget machinery is best-effort: `record()` no longer\n\t * emits `totals` updates, abort fan-out no longer fires. Treat the\n\t * bundle as terminated once disposed; long-running apps should\n\t * `dispose()` per gate instance to avoid the sub-leak documented\n\t * in `docs/optimizations.md`.\n\t */\n\tdispose(): void;\n}\n\nexport interface WithBudgetGateOptions {\n\tcaps: BudgetCaps;\n\t/**\n\t * Optional pricing function for USD gating. If omitted, `caps.usd` is\n\t * ignored (caps.calls / caps.inputTokens / caps.outputTokens still apply).\n\t */\n\tpricingFn?: PricingFn;\n\t/**\n\t * Edge-triggered: fires exactly once when the gate transitions from\n\t * open to closed. Subsequent invoke/stream attempts against a closed\n\t * gate do NOT re-fire `onExhausted` — use the reactive `isOpen` node\n\t * if you need per-attempt notifications. Receives the cap key that\n\t * triggered the transition.\n\t */\n\tonExhausted?: (which: keyof BudgetCaps) => void;\n\t/** Name for logs / describe output. */\n\tname?: string;\n\t/** Max events retained in the log (default 1000). */\n\tlogMax?: number;\n}\n\n// Frozen baseline shared for `totals.cache ?? EMPTY_TOTALS` reads. Consumers\n// that mutate their snapshot in place would otherwise poison every budget-gate\n// instance in the process. `reset()` emits a freshly-constructed object so\n// downstream identity-equals checks on the frozen constant don't false-equal.\nconst EMPTY_TOTALS: Readonly<BudgetTotals> = Object.freeze({\n\tcalls: 0,\n\tinputTokens: 0,\n\toutputTokens: 0,\n\tusd: 0,\n});\nconst makeEmptyTotals = (): BudgetTotals => ({\n\tcalls: 0,\n\tinputTokens: 0,\n\toutputTokens: 0,\n\tusd: 0,\n});\n\n/**\n * Wrap an adapter with budget enforcement. Returns `{adapter, budget}` so\n * callers can subscribe to the bundle for dashboards.\n */\nexport function withBudgetGate(\n\tinner: LLMAdapter,\n\topts: WithBudgetGateOptions,\n): { adapter: LLMAdapter; budget: LLMBudgetGateBundle } {\n\tconst log = reactiveLog<CallStatsEvent>(undefined, {\n\t\tname: opts.name ? `${opts.name}/log` : \"budgetGate/log\",\n\t\tmaxSize: opts.logMax ?? 1000,\n\t});\n\n\t// O(1) running totals — incremented per `record()` rather than reduced over\n\t// the full log. Reactive surface preserved via `state<BudgetTotals>`.\n\tconst totals = node<BudgetTotals>([], {\n\t\tname: opts.name ? `${opts.name}/totals` : \"budgetGate/totals\",\n\t\tinitial: makeEmptyTotals(),\n\t});\n\n\tconst isOpen = node<boolean>(\n\t\t[totals],\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 tt = data[0] as BudgetTotals;\n\t\t\tif (opts.caps.calls != null && tt.calls >= opts.caps.calls) {\n\t\t\t\tactions.emit(false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (opts.caps.inputTokens != null && tt.inputTokens >= opts.caps.inputTokens) {\n\t\t\t\tactions.emit(false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (opts.caps.outputTokens != null && tt.outputTokens >= opts.caps.outputTokens) {\n\t\t\t\tactions.emit(false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (opts.caps.usd != null && tt.usd >= opts.caps.usd) {\n\t\t\t\tactions.emit(false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tactions.emit(true);\n\t\t},\n\t\t{\n\t\t\tdescribeKind: \"derived\",\n\t\t\tname: opts.name ? `${opts.name}/isOpen` : \"budgetGate/isOpen\",\n\t\t\tinitial: true,\n\t\t},\n\t);\n\t// QA D2: capture every subscription/keepalive disposer so `dispose()`\n\t// can release the lot. Pre-D2 these were leaked for the process\n\t// lifetime; the leak grew with B9's abort-wire subscription.\n\tconst disposers: Array<() => void> = [];\n\tlet disposed = false;\n\t// Keep the isOpen derived live so `.cache` stays current without an external subscriber.\n\tdisposers.push(keepalive(isOpen));\n\n\t// Edge-trigger `onExhausted` on the open→closed transition. Subscribing\n\t// here (instead of firing from `buildClosedError`) ensures the callback\n\t// fires exactly once per transition, regardless of how many invoke/stream\n\t// attempts hit the closed gate afterward. Callers that want per-attempt\n\t// notifications should subscribe to `isOpen` directly.\n\tif (opts.onExhausted != null) {\n\t\tconst handler = opts.onExhausted;\n\t\t// Seed `wasOpen` from the FIRST observed DATA rather than assuming\n\t\t// `true`. If caps are already exhausted at construction (e.g.\n\t\t// `calls: 0` or a pre-filled totals source), the push-on-subscribe\n\t\t// DATA=`false` would otherwise be interpreted as an open→closed\n\t\t// transition and fire `onExhausted` before any invoke has been\n\t\t// attempted. `seeded` guards that first observation.\n\t\tlet seeded = false;\n\t\tlet wasOpen = true;\n\t\tconst unsub = isOpen.subscribe((msgs) => {\n\t\t\tfor (const m of msgs) {\n\t\t\t\tif (m[0] === DATA) {\n\t\t\t\t\tconst v = m[1] as boolean;\n\t\t\t\t\tif (seeded && wasOpen && v === false) {\n\t\t\t\t\t\tconst which = pickExhaustedKey(totals.cache ?? EMPTY_TOTALS, opts.caps);\n\t\t\t\t\t\tif (which) handler(which);\n\t\t\t\t\t}\n\t\t\t\t\twasOpen = v;\n\t\t\t\t\tseeded = true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tdisposers.push(unsub);\n\t}\n\n\tconst buildClosedError = (): BudgetExhaustedError | undefined => {\n\t\tif (isOpen.cache === false) {\n\t\t\tconst t = totals.cache ?? EMPTY_TOTALS;\n\t\t\tconst which = pickExhaustedKey(t, opts.caps);\n\t\t\treturn new BudgetExhaustedError(\n\t\t\t\twhich ?? \"budget\",\n\t\t\t\topts.caps[which ?? \"calls\"] ?? 0,\n\t\t\t\twhichValue(t, which ?? \"calls\"),\n\t\t\t);\n\t\t}\n\t\treturn undefined;\n\t};\n\n\tconst record = (\n\t\tusage: TokenUsage,\n\t\tmeta: {\n\t\t\tmodel: string;\n\t\t\ttier?: string;\n\t\t\tstartNs: number;\n\t\t\tmethod: \"invoke\" | \"stream\";\n\t\t\terror?: { type: string; message: string };\n\t\t},\n\t): void => {\n\t\tconst provider = inner.provider;\n\t\tconst event: CallStatsEvent = buildCallStats({\n\t\t\tprovider,\n\t\t\tmodel: meta.model,\n\t\t\ttier: meta.tier,\n\t\t\tusage,\n\t\t\tstartNs: meta.startNs,\n\t\t\tmethod: meta.method,\n\t\t\t...(meta.error ? { error: meta.error } : {}),\n\t\t});\n\t\tlog.append(event);\n\t\tconst prev = totals.cache ?? EMPTY_TOTALS;\n\t\tconst usd = opts.pricingFn\n\t\t\t? prev.usd + opts.pricingFn(usage, { model: meta.model, provider, tier: meta.tier }).total\n\t\t\t: prev.usd;\n\t\ttotals.emit({\n\t\t\tcalls: prev.calls + 1,\n\t\t\tinputTokens: prev.inputTokens + sumInputTokens(usage),\n\t\t\toutputTokens: prev.outputTokens + sumOutputTokens(usage),\n\t\t\tusd,\n\t\t});\n\t};\n\n\tconst reset = (): void => {\n\t\tlog.clear();\n\t\ttotals.emit(makeEmptyTotals());\n\t};\n\n\t// Lock 3.C (Phase 13.6.B): auto-wire adapter abort. Track in-flight\n\t// controllers so the open→closed transition can cancel calls that\n\t// started before the budget exhausted. Encodes L2.42-honest-cost's\n\t// \"two pieces needed\" rule (observability bubble + auto-wired abort)\n\t// into the primitive itself — no manual hookup required.\n\t//\n\t// DS-14.5 / AB-1: honoring `opts.signal` is now a hard adapter\n\t// contract (the `abortCapable` flag + this dev-mode warning were\n\t// removed pre-1.0). The budget gate fans out the AbortSignal on\n\t// exhaustion and every adapter is required to cancel its underlying\n\t// I/O — no escape hatch, no silent burn-through.\n\tconst inflight = new Set<AbortController>();\n\tlet isOpenSeeded = false;\n\tlet isOpenWasOpen = true;\n\tconst isOpenAbortUnsub = isOpen.subscribe((msgs) => {\n\t\tfor (const m of msgs) {\n\t\t\tif (m[0] !== DATA) continue;\n\t\t\tconst v = m[1] as boolean;\n\t\t\tif (isOpenSeeded && isOpenWasOpen && v === false && inflight.size > 0) {\n\t\t\t\tconst reason = buildClosedError() ?? new Error(\"budget exhausted\");\n\t\t\t\tfor (const ctrl of inflight) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tctrl.abort(reason);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t/* best-effort abort fan-out */\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tisOpenWasOpen = v;\n\t\t\tisOpenSeeded = true;\n\t\t}\n\t});\n\tdisposers.push(isOpenAbortUnsub);\n\n\tfunction combineSignals(callerSignal: AbortSignal | undefined): {\n\t\tctrl: AbortController;\n\t\tcleanup: () => void;\n\t} {\n\t\tconst ctrl = new AbortController();\n\t\t// If the budget is already closed when invoke starts, abort\n\t\t// immediately so the inner call never starts.\n\t\tif (isOpen.cache === false) {\n\t\t\tctrl.abort(buildClosedError() ?? new Error(\"budget exhausted\"));\n\t\t}\n\t\tconst onCallerAbort = (): void => {\n\t\t\tif (!ctrl.signal.aborted) ctrl.abort((callerSignal as AbortSignal).reason);\n\t\t};\n\t\tif (callerSignal != null) {\n\t\t\tif (callerSignal.aborted) {\n\t\t\t\tctrl.abort(callerSignal.reason);\n\t\t\t} else {\n\t\t\t\tcallerSignal.addEventListener(\"abort\", onCallerAbort, { once: true });\n\t\t\t}\n\t\t}\n\t\tinflight.add(ctrl);\n\t\tconst cleanup = (): void => {\n\t\t\tinflight.delete(ctrl);\n\t\t\tif (callerSignal != null) callerSignal.removeEventListener(\"abort\", onCallerAbort);\n\t\t};\n\t\treturn { ctrl, cleanup };\n\t}\n\n\tconst wrap: LLMAdapter = adapterWrapper(inner, {\n\t\tinvoke(messages, invokeOpts) {\n\t\t\tconst closedErr = buildClosedError();\n\t\t\tif (closedErr) return Promise.reject(closedErr);\n\t\t\tconst startNs = monotonicNs();\n\t\t\tconst model = inner.model ?? invokeOpts?.model ?? \"\";\n\t\t\tconst { ctrl, cleanup } = combineSignals(invokeOpts?.signal);\n\t\t\tconst recordResp = (resp: LLMResponse): LLMResponse => {\n\t\t\t\tcleanup();\n\t\t\t\trecord(resp.usage ?? emptyUsageStub(), {\n\t\t\t\t\tmodel: inner.model ?? invokeOpts?.model ?? resp.model ?? \"\",\n\t\t\t\t\ttier: invokeOpts?.tier ?? resp.tier,\n\t\t\t\t\tstartNs,\n\t\t\t\t\tmethod: \"invoke\",\n\t\t\t\t});\n\t\t\t\treturn resp;\n\t\t\t};\n\t\t\tconst recordErr = (err: unknown): void => {\n\t\t\t\tcleanup();\n\t\t\t\tconst e = err as Error | undefined;\n\t\t\t\trecord(emptyUsageStub(), {\n\t\t\t\t\tmodel,\n\t\t\t\t\ttier: invokeOpts?.tier,\n\t\t\t\t\tstartNs,\n\t\t\t\t\tmethod: \"invoke\",\n\t\t\t\t\terror: { type: e?.name ?? \"Error\", message: e?.message ?? String(err) },\n\t\t\t\t});\n\t\t\t};\n\t\t\tconst innerOpts = { ...(invokeOpts ?? {}), signal: ctrl.signal };\n\t\t\treturn adaptInvokeResult(inner.invoke(messages, innerOpts), {\n\t\t\t\tonResp: recordResp,\n\t\t\t\tonError: recordErr,\n\t\t\t\tname: \"budgetGate/invokeTap\",\n\t\t\t});\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst closedErr = buildClosedError();\n\t\t\tif (closedErr) throw closedErr;\n\t\t\tconst startNs = monotonicNs();\n\t\t\tlet finalUsage: TokenUsage | undefined;\n\t\t\tconst { ctrl, cleanup } = combineSignals(invokeOpts?.signal);\n\t\t\tconst innerOpts = { ...(invokeOpts ?? {}), signal: ctrl.signal };\n\t\t\ttry {\n\t\t\t\tfor await (const delta of inner.stream(messages, innerOpts)) {\n\t\t\t\t\tif (delta.type === \"usage\") finalUsage = delta.usage;\n\t\t\t\t\tyield delta;\n\t\t\t\t}\n\t\t\t\tcleanup();\n\t\t\t\trecord(finalUsage ?? emptyUsageStub(), {\n\t\t\t\t\tmodel: inner.model ?? invokeOpts?.model ?? \"\",\n\t\t\t\t\ttier: invokeOpts?.tier,\n\t\t\t\t\tstartNs,\n\t\t\t\t\tmethod: \"stream\",\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\tcleanup();\n\t\t\t\tconst error = err as Error;\n\t\t\t\trecord(finalUsage ?? emptyUsageStub(), {\n\t\t\t\t\tmodel: inner.model ?? invokeOpts?.model ?? \"\",\n\t\t\t\t\ttier: invokeOpts?.tier,\n\t\t\t\t\tstartNs,\n\t\t\t\t\tmethod: \"stream\",\n\t\t\t\t\terror: { type: error?.name ?? \"Error\", message: error?.message ?? String(err) },\n\t\t\t\t});\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\t});\n\n\twithLayer(wrap, \"withBudgetGate\", inner);\n\n\tconst dispose = (): void => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\t// Defensive last gasp: abort any in-flight controllers so the\n\t\t// awaited Promises don't strand their callers waiting on a soon-\n\t\t// to-be-disposed adapter.\n\t\tconst reason = new Error(\"withBudgetGate disposed\");\n\t\tfor (const ctrl of inflight) {\n\t\t\ttry {\n\t\t\t\tctrl.abort(reason);\n\t\t\t} catch {\n\t\t\t\t/* best-effort */\n\t\t\t}\n\t\t}\n\t\tinflight.clear();\n\t\tfor (const d of disposers) {\n\t\t\ttry {\n\t\t\t\td();\n\t\t\t} catch {\n\t\t\t\t/* best-effort */\n\t\t\t}\n\t\t}\n\t\tdisposers.length = 0;\n\t};\n\n\treturn { adapter: wrap, budget: { totals, isOpen, log, reset, dispose } };\n}\n\nfunction pickExhaustedKey(t: BudgetTotals, caps: BudgetCaps): keyof BudgetCaps | undefined {\n\tif (caps.calls != null && t.calls >= caps.calls) return \"calls\";\n\tif (caps.inputTokens != null && t.inputTokens >= caps.inputTokens) return \"inputTokens\";\n\tif (caps.outputTokens != null && t.outputTokens >= caps.outputTokens) return \"outputTokens\";\n\tif (caps.usd != null && t.usd >= caps.usd) return \"usd\";\n\treturn undefined;\n}\n\nfunction whichValue(t: BudgetTotals, which: keyof BudgetCaps): number {\n\tswitch (which) {\n\t\tcase \"calls\":\n\t\t\treturn t.calls;\n\t\tcase \"inputTokens\":\n\t\t\treturn t.inputTokens;\n\t\tcase \"outputTokens\":\n\t\t\treturn t.outputTokens;\n\t\tcase \"usd\":\n\t\t\treturn t.usd;\n\t}\n}\n\nexport type { ChatMessage, LLMInvokeOptions };\n","/**\n * `withDryRun` — short-circuit to a fake adapter when a flag is on.\n *\n * Useful for CI / preflight / cost-safety pipelines: wrap a real adapter,\n * pass `enabled: true` (or a reactive flag) to bypass the wire call. Default\n * shim is {@link dryRunAdapter}; callers can supply their own.\n *\n * **Returns `{adapter, dispose}`** — call `dispose()` to release the internal\n * keepalive on the reactive `enabled` input. Long-lived adapter instances\n * (module-level singletons) can ignore dispose; transient adapters (per-\n * request or per-user) should call it on teardown to allow the source to\n * be GC'd.\n */\n\nimport { fromAny, keepalive, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { adapterWrapper, withLayer } from \"../_internal/wrappers.js\";\nimport type { LLMAdapter } from \"../core/types.js\";\nimport { dryRunAdapter } from \"../providers/dry-run.js\";\n\nexport interface WithDryRunOptions {\n\t/**\n\t * Toggle — `true` always dry-runs; `false` always passes through; a\n\t * `NodeInput<boolean>` reads the current value at call time (factory-time\n\t * seed pattern, live-tunable).\n\t */\n\tenabled: NodeInput<boolean>;\n\t/** Dry-run adapter override. Default: `dryRunAdapter({ provider: inner.provider, model: inner.model })`. */\n\tmock?: LLMAdapter;\n}\n\nexport interface WithDryRunBundle {\n\tadapter: LLMAdapter;\n\t/**\n\t * Release the internal keepalive subscription on the reactive `enabled`\n\t * input. Idempotent. Safe to ignore on long-lived adapters.\n\t */\n\tdispose(): void;\n}\n\nexport function withDryRun(inner: LLMAdapter, opts: WithDryRunOptions): WithDryRunBundle {\n\tconst mock = opts.mock ?? dryRunAdapter({ provider: inner.provider, model: inner.model });\n\n\t// Normalize the enabled input: literal boolean stays literal; NodeInput<boolean>\n\t// gets bridged so we can read .cache at call time (factory-time seed per\n\t// COMPOSITION-GUIDE §28). Keep the node alive so push-on-subscribe and\n\t// derived-chain recomputation keep the cache current — otherwise a reactive\n\t// flag would stay at its initial value forever.\n\tconst enabledLiteral = typeof opts.enabled === \"boolean\" ? (opts.enabled as boolean) : undefined;\n\tconst enabledNode =\n\t\tenabledLiteral === undefined ? fromAny(opts.enabled as NodeInput<boolean>) : undefined;\n\tlet unsubKeepalive: (() => void) | undefined;\n\tif (enabledNode) unsubKeepalive = keepalive(enabledNode);\n\n\tconst isEnabled = (): boolean => {\n\t\tif (enabledLiteral !== undefined) return enabledLiteral;\n\t\treturn Boolean(enabledNode?.cache);\n\t};\n\n\tconst adapter: LLMAdapter = adapterWrapper(inner, {\n\t\tinvoke(messages, invokeOpts) {\n\t\t\treturn isEnabled() ? mock.invoke(messages, invokeOpts) : inner.invoke(messages, invokeOpts);\n\t\t},\n\n\t\tstream(messages, invokeOpts) {\n\t\t\treturn isEnabled() ? mock.stream(messages, invokeOpts) : inner.stream(messages, invokeOpts);\n\t\t},\n\t});\n\twithLayer(adapter, \"withDryRun\", inner);\n\n\tconst dispose = (): void => {\n\t\tif (unsubKeepalive) {\n\t\t\tunsubKeepalive();\n\t\t\tunsubKeepalive = undefined;\n\t\t}\n\t};\n\n\treturn { adapter, dispose };\n}\n","/**\n * HTTP 429 / rate-limit parser.\n *\n * Produces a {@link RateLimitSignal} from provider HTTP errors so adaptive\n * rate limiters can tighten effective limits. Normalizes:\n * - `Retry-After` (seconds or HTTP-date)\n * - `x-ratelimit-reset` / `x-ratelimit-reset-tokens` (epoch secs or duration)\n * - `x-ratelimit-remaining-{requests,tokens}` + `x-ratelimit-limit-*`\n * - Anthropic `anthropic-ratelimit-*` headers\n * - OpenAI / OpenRouter / Groq headers (same family)\n * - Error message regex fallbacks for providers without structured headers\n */\n\nimport type { RateLimitSignal } from \"../../../resilience/adaptive-rate-limiter.js\";\n\nexport interface HttpErrorLike {\n\tstatus?: number;\n\theaders?: Headers | Record<string, string | string[] | undefined>;\n\tmessage?: string;\n}\n\n/**\n * Extract a {@link RateLimitSignal} from a fetch-style error object, a Response,\n * or any object exposing `.status` + `.headers` + `.message`.\n *\n * Returns `undefined` if no rate-limit information can be extracted.\n */\nexport function parseRateLimitFromError(err: unknown): RateLimitSignal | undefined {\n\tif (err == null || typeof err !== \"object\") return undefined;\n\tconst like = err as HttpErrorLike;\n\tconst status = like.status;\n\tconst headerLookup = toHeaderGetter(like.headers);\n\n\t// Only respond on 429 or 503 (some providers use 503 for rate-limits).\n\tif (status !== 429 && status !== 503 && !looksLikeRateLimitMessage(like.message)) {\n\t\treturn undefined;\n\t}\n\n\tconst sig: RateLimitSignal = {};\n\n\tconst retryAfter = headerLookup(\"retry-after\");\n\tconst retryAfterMs = parseRetryAfter(retryAfter);\n\tif (retryAfterMs != null) sig.retryAfterMs = retryAfterMs;\n\n\t// Anthropic: anthropic-ratelimit-requests-reset (ISO-8601 timestamp)\n\tconst anthReqReset = headerLookup(\"anthropic-ratelimit-requests-reset\");\n\tif (anthReqReset) {\n\t\tconst ms = parseIsoResetHeaderToDelayMs(anthReqReset);\n\t\tif (ms != null) sig.retryAfterMs = Math.max(sig.retryAfterMs ?? 0, ms);\n\t}\n\tconst anthTokReset = headerLookup(\"anthropic-ratelimit-tokens-reset\");\n\tif (anthTokReset) {\n\t\tconst ms = parseIsoResetHeaderToDelayMs(anthTokReset);\n\t\tif (ms != null) sig.retryAfterMs = Math.max(sig.retryAfterMs ?? 0, ms);\n\t}\n\n\t// OpenAI / OpenRouter / Groq: x-ratelimit-limit-requests, -reset-requests, etc.\n\tconst limitRequests = numHeader(headerLookup, \"x-ratelimit-limit-requests\");\n\tif (limitRequests != null) sig.rpmCap = limitRequests;\n\tconst limitTokens = numHeader(headerLookup, \"x-ratelimit-limit-tokens\");\n\tif (limitTokens != null) sig.tpmCap = limitTokens;\n\n\t// Usage hint: remaining / limit\n\tconst remainingReq = numHeader(headerLookup, \"x-ratelimit-remaining-requests\");\n\tconst remainingTok = numHeader(headerLookup, \"x-ratelimit-remaining-tokens\");\n\tif (remainingReq != null && limitRequests != null && limitRequests > 0) {\n\t\tsig.usageHint ??= {};\n\t\tsig.usageHint.rpm = 1 - remainingReq / limitRequests;\n\t}\n\tif (remainingTok != null && limitTokens != null && limitTokens > 0) {\n\t\tsig.usageHint ??= {};\n\t\tsig.usageHint.tpm = 1 - remainingTok / limitTokens;\n\t}\n\n\t// Fallback: parse retry-after from error message if no header was found.\n\tif (sig.retryAfterMs == null && like.message) {\n\t\tconst msgMs = parseRetryAfterFromMessage(like.message);\n\t\tif (msgMs != null) sig.retryAfterMs = msgMs;\n\t}\n\n\t// Preserve raw headers for user-specific downstream logic.\n\tif (like.headers) sig.metadata = { headers: serializeHeaders(like.headers) };\n\n\tif (\n\t\tsig.retryAfterMs == null &&\n\t\tsig.rpmCap == null &&\n\t\tsig.tpmCap == null &&\n\t\tsig.usageHint == null\n\t) {\n\t\t// Nothing actionable extracted — still emit empty signal so consumers can\n\t\t// count occurrences (metadata carries the headers).\n\t\treturn sig.metadata ? sig : undefined;\n\t}\n\n\treturn sig;\n}\n\n// ---------------------------------------------------------------------------\n// Header access\n// ---------------------------------------------------------------------------\n\ntype HeaderGetter = (name: string) => string | undefined;\n\nfunction toHeaderGetter(h: HttpErrorLike[\"headers\"]): HeaderGetter {\n\tif (!h) return () => undefined;\n\tif (typeof (h as Headers).get === \"function\") {\n\t\tconst hh = h as Headers;\n\t\treturn (name) => hh.get(name) ?? hh.get(name.toLowerCase()) ?? undefined;\n\t}\n\tconst record = h as Record<string, string | string[] | undefined>;\n\tconst lc: Record<string, string | undefined> = {};\n\tfor (const [k, v] of Object.entries(record)) {\n\t\tconst sv = Array.isArray(v) ? v.join(\", \") : v;\n\t\tif (sv != null) lc[k.toLowerCase()] = sv;\n\t}\n\treturn (name) => lc[name.toLowerCase()];\n}\n\nfunction serializeHeaders(h: NonNullable<HttpErrorLike[\"headers\"]>): Record<string, string> {\n\tconst out: Record<string, string> = {};\n\tif (typeof (h as Headers).forEach === \"function\") {\n\t\t(h as Headers).forEach((v, k) => {\n\t\t\tout[k] = v;\n\t\t});\n\t\treturn out;\n\t}\n\tfor (const [k, v] of Object.entries(h as Record<string, string | string[] | undefined>)) {\n\t\tif (v != null) out[k] = Array.isArray(v) ? v.join(\", \") : v;\n\t}\n\treturn out;\n}\n\nfunction numHeader(getter: HeaderGetter, name: string): number | undefined {\n\tconst raw = getter(name);\n\tif (raw == null) return undefined;\n\tconst n = Number(raw);\n\treturn Number.isFinite(n) ? n : undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Retry-after parsing\n// ---------------------------------------------------------------------------\n\nfunction parseRetryAfter(raw: string | undefined): number | undefined {\n\tif (!raw) return undefined;\n\tconst trimmed = raw.trim();\n\tconst asNum = Number(trimmed);\n\tif (Number.isFinite(asNum) && asNum >= 0) return asNum * 1000;\n\t// HTTP-date fallback.\n\tconst ts = Date.parse(trimmed);\n\tif (Number.isFinite(ts)) {\n\t\tconst delta = ts - Date.now();\n\t\tif (delta > 0) return delta;\n\t}\n\treturn undefined;\n}\n\n/**\n * Parse an Anthropic `anthropic-ratelimit-{requests,tokens}-reset` header\n * into a delay (milliseconds until reset). These headers are documented\n * as ISO-8601 absolute timestamps; we use `Date.parse` and clamp to zero\n * for headers that have already elapsed. Returns `undefined` for unparseable\n * values — no numeric-epoch heuristic (providers don't send numeric resets\n * here, and the old heuristic was ambiguous across seconds-vs-millis).\n */\nfunction parseIsoResetHeaderToDelayMs(raw: string): number | undefined {\n\tif (!raw) return undefined;\n\tconst ts = Date.parse(raw);\n\tif (Number.isFinite(ts)) return Math.max(0, ts - Date.now());\n\treturn undefined;\n}\n\nconst RETRY_MSG_RE = /retry\\s+(?:in|after)\\s+(\\d+(?:\\.\\d+)?)\\s*(ms|s|sec|seconds?|m|min|minutes?)/i;\n\nfunction parseRetryAfterFromMessage(msg: string): number | undefined {\n\tconst m = RETRY_MSG_RE.exec(msg);\n\tif (!m) return undefined;\n\tconst n = Number(m[1]);\n\tif (!Number.isFinite(n)) return undefined;\n\tconst unit = (m[2] ?? \"s\").toLowerCase();\n\tif (unit === \"ms\") return n;\n\tif (unit.startsWith(\"s\")) return n * 1000;\n\tif (unit.startsWith(\"m\")) return n * 60_000;\n\treturn undefined;\n}\n\nconst RATE_LIMIT_MSG_RE = /rate\\s*limit|too\\s*many\\s*requests|quota|429/i;\n\nfunction looksLikeRateLimitMessage(msg: string | undefined): boolean {\n\treturn !!msg && RATE_LIMIT_MSG_RE.test(msg);\n}\n","/**\n * `withRateLimiter` — adapter middleware bridging to the reactive\n * `adaptiveRateLimiter` primitive.\n *\n * - Consumes live `rpm`/`tpm` caps as reactive `NodeInput<number>` so\n * callers can retune at runtime (e.g. from a `ModelLimits.rpm` node).\n * - Adapts to provider 429 responses via `http429Parser` fed into the\n * limiter's `adaptation` signal.\n * - `costFn` estimates token cost pre-call (e.g. char-based approximation);\n * the post-call actual usage is fed back via `limiter.recordUsage()`.\n */\n\nimport { fromAny, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { firstValueFrom } from \"../../../../base/sources/settled.js\";\nimport {\n\ttype AdaptiveRateLimiterBundle,\n\tadaptiveRateLimiter,\n\ttype RateLimitSignal,\n} from \"../../../resilience/adaptive-rate-limiter.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\";\nimport { emptyUsage, sumInputTokens, sumOutputTokens } from \"../core/types.js\";\nimport { parseRateLimitFromError } from \"./http429-parser.js\";\n\nexport interface WithRateLimiterOptions {\n\t/** Live rpm cap (defaults to `Infinity`). */\n\trpm?: NodeInput<number>;\n\t/** Live tpm cap (defaults to `Infinity`). */\n\ttpm?: NodeInput<number>;\n\t/**\n\t * Pre-call token-cost estimate. Default: 0 (only rpm gates). Override with\n\t * e.g. a char-based heuristic:\n\t * `(msgs) => Math.ceil(msgs.reduce((s, m) => s + m.content.length, 0) / 4)`.\n\t */\n\tcostFn?: (messages: readonly ChatMessage[], opts?: LLMInvokeOptions) => number;\n\t/**\n\t * Manual adaptation signal source. Defaults to a signal derived from\n\t * provider errors via `parseRateLimitFromError` — users can supply a\n\t * custom signal chain if they route errors elsewhere.\n\t */\n\tadaptation?: NodeInput<RateLimitSignal>;\n\tburstMultiplier?: number;\n\tname?: string;\n\t/**\n\t * Share an existing {@link AdaptiveRateLimiterBundle} across multiple\n\t * adapter wraps. When provided, `withRateLimiter` reuses this bundle\n\t * instead of constructing a new one — useful when the RPM/TPM cap is\n\t * logically per-provider but the caller wants to harden multiple adapters\n\t * (e.g. primary + fallback of the same vendor) against the shared cap.\n\t *\n\t * When `limiter` is set, `rpm` / `tpm` / `adaptation` / `burstMultiplier`\n\t * / `name` are ignored (the supplied bundle owns those). `costFn` is still\n\t * used per-wrap — each wrap supplies its own cost estimator.\n\t */\n\tlimiter?: AdaptiveRateLimiterBundle;\n}\n\n/**\n * Wrap an adapter with adaptive rate limiting. Returns `{adapter, limiter}`\n * so callers can subscribe to limiter internals (rpmAvailable, pending, etc.)\n * for dashboards.\n */\nexport function withRateLimiter(\n\tinner: LLMAdapter,\n\topts: WithRateLimiterOptions = {},\n): { adapter: LLMAdapter; limiter: AdaptiveRateLimiterBundle } {\n\tconst limiter =\n\t\topts.limiter ??\n\t\tadaptiveRateLimiter({\n\t\t\tname: opts.name ?? \"rateLimiter\",\n\t\t\trpm: opts.rpm,\n\t\t\ttpm: opts.tpm,\n\t\t\tadaptation: opts.adaptation,\n\t\t\tburstMultiplier: opts.burstMultiplier,\n\t\t});\n\n\tconst estimateCost = (\n\t\tmessages: readonly ChatMessage[],\n\t\tinvokeOpts: LLMInvokeOptions | undefined,\n\t): number => {\n\t\tif (opts.costFn) return opts.costFn(messages, invokeOpts);\n\t\treturn 0;\n\t};\n\n\tconst handleError = (err: unknown): void => {\n\t\tconst sig = parseRateLimitFromError(err);\n\t\tif (sig) limiter.recordSignal(sig);\n\t};\n\n\tconst wrap: LLMAdapter = adapterWrapper(inner, {\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst tokenCost = estimateCost(messages, invokeOpts);\n\t\t\tawait limiter.acquire({ requestCost: 1, tokenCost, signal: invokeOpts?.signal });\n\t\t\ttry {\n\t\t\t\tconst resp = await firstValueFrom(fromAny(inner.invoke(messages, invokeOpts)));\n\t\t\t\tconst usage = resp.usage ?? emptyUsage();\n\t\t\t\tconst actual = sumInputTokens(usage) + sumOutputTokens(usage);\n\t\t\t\tconst delta = actual - tokenCost;\n\t\t\t\tif (delta > 0) limiter.recordUsage(delta);\n\t\t\t\treturn resp;\n\t\t\t} catch (err) {\n\t\t\t\thandleError(err);\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst tokenCost = estimateCost(messages, invokeOpts);\n\t\t\tawait limiter.acquire({ requestCost: 1, tokenCost, signal: invokeOpts?.signal });\n\t\t\ttry {\n\t\t\t\tlet finalTokens = 0;\n\t\t\t\tfor await (const delta of inner.stream(messages, invokeOpts)) {\n\t\t\t\t\tif (delta.type === \"usage\") {\n\t\t\t\t\t\tfinalTokens = sumInputTokens(delta.usage) + sumOutputTokens(delta.usage);\n\t\t\t\t\t}\n\t\t\t\t\tyield delta;\n\t\t\t\t}\n\t\t\t\tconst d = finalTokens - tokenCost;\n\t\t\t\tif (d > 0) limiter.recordUsage(d);\n\t\t\t} catch (err) {\n\t\t\t\thandleError(err);\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\t});\n\twithLayer(wrap, \"withRateLimiter\", inner);\n\n\treturn { adapter: wrap, limiter };\n}\n","/**\n * `withRetry` — retry `invoke()` / `stream()` on transient errors.\n *\n * Streaming retry is tricky: we retry only if the stream fails before\n * yielding any tokens. Once tokens have started flowing, we surface the\n * error to avoid replaying from scratch (which would double-bill and\n * confuse consumers). Opt out of streaming retry via `opts.retryStreaming = false`.\n *\n * Uses `ResettableTimer` for backoff sleeps (spec §5.10 escape hatch, same\n * pattern as `extra/resilience.ts`). Abort-aware — early-aborts before the\n * first attempt and cleans up the abort listener on both the timer-fires\n * and abort paths.\n */\n\nimport { ResettableTimer } from \"@graphrefly/pure-ts/core\";\nimport { fromAny } from \"@graphrefly/pure-ts/extra\";\nimport { firstValueFrom } from \"../../../../base/sources/settled.js\";\nimport { adapterWrapper, withLayer } from \"../_internal/wrappers.js\";\nimport type { LLMAdapter, LLMResponse, StreamDelta } from \"../core/types.js\";\n\nexport interface WithRetryOptions {\n\t/** Max total attempts (including the first). Default 3. */\n\tattempts?: number;\n\t/** Base delay in ms. Default 500. */\n\tbaseDelayMs?: number;\n\t/** Max delay in ms. Default 10_000. */\n\tmaxDelayMs?: number;\n\t/**\n\t * Delay strategy. Default `\"decorrelated\"` — AWS-style `random(baseDelay,\n\t * min(maxDelay, prev * 3))` which smooths retry storms and matches common\n\t * SDK expectations. `\"exp\"` and `\"linear\"` produce deterministic schedules\n\t * when `jitter: false`.\n\t */\n\tstrategy?: \"exp\" | \"linear\" | \"decorrelated\";\n\t/**\n\t * Add randomized jitter. Ignored for `strategy: \"decorrelated\"` (which is\n\t * inherently jittered). For `exp`/`linear`, symmetric jitter in `[0.5x,\n\t * 1.5x]` of the nominal delay.\n\t */\n\tjitter?: boolean;\n\t/**\n\t * Predicate: should this error trigger a retry? Default retries network /\n\t * 5xx / 429 / transient errors, but not 4xx (other than 429), aborts, or\n\t * `BudgetExhaustedError` from upstream middleware.\n\t */\n\tshouldRetry?: (err: unknown, attempt: number) => boolean;\n\t/** Retry streaming calls if they fail pre-first-token. Default true. */\n\tretryStreaming?: boolean;\n}\n\nfunction makeAbortError(reason = \"aborted\"): Error {\n\tconst err = new Error(reason) as Error & { name: string };\n\terr.name = \"AbortError\";\n\treturn err;\n}\n\n/**\n * Promise-based abort-aware sleep using `ResettableTimer`.\n * Spec §5.10 escape hatch — same pattern as `extra/resilience.ts`.\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\nexport function withRetry(inner: LLMAdapter, opts: WithRetryOptions = {}): LLMAdapter {\n\tconst attempts = opts.attempts ?? 3;\n\tconst baseDelayMs = opts.baseDelayMs ?? 500;\n\tconst maxDelayMs = opts.maxDelayMs ?? 10_000;\n\tconst strategy = opts.strategy ?? \"decorrelated\";\n\tconst jitter = opts.jitter ?? true;\n\tconst shouldRetry = opts.shouldRetry ?? defaultShouldRetry;\n\tconst retryStreaming = opts.retryStreaming ?? true;\n\n\t// Decorrelated state — carried across the same acquire's retries.\n\tconst delay = (attempt: number, prevDelay: number): number => {\n\t\tif (strategy === \"decorrelated\") {\n\t\t\t// AWS-style: random(baseDelay, min(maxDelay, prevDelay * 3))\n\t\t\tconst upper = Math.min(maxDelayMs, Math.max(baseDelayMs, prevDelay * 3));\n\t\t\treturn baseDelayMs + Math.random() * (upper - baseDelayMs);\n\t\t}\n\t\tconst nominal = strategy === \"exp\" ? baseDelayMs * 2 ** (attempt - 1) : baseDelayMs * attempt;\n\t\tconst bounded = Math.min(maxDelayMs, nominal);\n\t\tif (!jitter) return bounded;\n\t\t// Symmetric jitter: bounded * [0.5, 1.5), clamped.\n\t\tconst jittered = bounded * (0.5 + Math.random());\n\t\treturn Math.min(maxDelayMs, jittered);\n\t};\n\n\tconst wrap = adapterWrapper(inner, {\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tif (invokeOpts?.signal?.aborted) throw makeAbortError();\n\t\t\tlet lastErr: unknown;\n\t\t\tlet prevDelay = baseDelayMs;\n\t\t\tfor (let attempt = 1; attempt <= attempts; attempt++) {\n\t\t\t\ttry {\n\t\t\t\t\treturn await firstValueFrom(fromAny(inner.invoke(messages, invokeOpts)));\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlastErr = err;\n\t\t\t\t\tif (attempt >= attempts || !shouldRetry(err, attempt)) throw err;\n\t\t\t\t\tconst waitMs = delay(attempt, prevDelay);\n\t\t\t\t\tprevDelay = waitMs;\n\t\t\t\t\tawait sleep(waitMs, invokeOpts?.signal);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow lastErr;\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tif (invokeOpts?.signal?.aborted) throw makeAbortError();\n\t\t\tif (!retryStreaming) {\n\t\t\t\tfor await (const d of inner.stream(messages, invokeOpts)) yield d;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet lastErr: unknown;\n\t\t\tlet prevDelay = baseDelayMs;\n\t\t\tfor (let attempt = 1; attempt <= attempts; attempt++) {\n\t\t\t\tlet yieldedAny = false;\n\t\t\t\ttry {\n\t\t\t\t\tfor await (const d of inner.stream(messages, invokeOpts)) {\n\t\t\t\t\t\tyieldedAny = true;\n\t\t\t\t\t\tyield d;\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlastErr = err;\n\t\t\t\t\tif (yieldedAny) throw err;\n\t\t\t\t\tif (attempt >= attempts || !shouldRetry(err, attempt)) throw err;\n\t\t\t\t\tconst waitMs = delay(attempt, prevDelay);\n\t\t\t\t\tprevDelay = waitMs;\n\t\t\t\t\tawait sleep(waitMs, invokeOpts?.signal);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow lastErr;\n\t\t},\n\t});\n\twithLayer(wrap, \"withRetry\", inner);\n\treturn wrap;\n}\n\nfunction defaultShouldRetry(err: unknown, _attempt: number): boolean {\n\tif (err == null) return false;\n\tconst e = err as { name?: string; status?: number; code?: string; message?: string };\n\t// Timeout-family errors — retry by default so each attempt re-arms the\n\t// per-attempt deadline set by `withLLMTimeout`. Checked BEFORE the abort\n\t// guards below because `withLLMTimeout` re-throws its timer-fire path as\n\t// `LLMTimeoutError` even when the underlying fetch rejected with\n\t// AbortError.\n\tif (e.name === \"LLMTimeoutError\") return true;\n\t// Abort-family errors — never retry (caller initiated).\n\tif (e.name === \"AbortError\") return false;\n\tif (e.message === \"aborted\") return false;\n\tif (e.name === \"DOMException\" && e.code != null && Number(e.code) === 20 /* ABORT_ERR */) {\n\t\treturn false;\n\t}\n\tif (e.name === \"BudgetExhaustedError\") return false;\n\tif (e.name === \"CircuitOpenError\") return false;\n\tif (e.status != null) {\n\t\tif (e.status === 429) return true;\n\t\tif (e.status >= 500 && e.status < 600) return true;\n\t\treturn false;\n\t}\n\t// Network-level errors often have codes like ECONNRESET, ENOTFOUND, etc.\n\tif (e.code && typeof e.code === \"string\") {\n\t\tif (/^E[A-Z]+$/.test(e.code)) return true;\n\t}\n\tif (e.message) {\n\t\treturn /network|timeout|socket|fetch|econn|eai_/i.test(e.message);\n\t}\n\treturn false;\n}\n","/**\n * `withLLMTimeout` — cancel `invoke()` / `stream()` after `ms` elapse.\n *\n * Wires a child AbortSignal so provider adapters can honor the cancellation\n * (all shipped adapters forward `signal` through to their fetch / SDK call).\n *\n * Uses `ResettableTimer` rather than raw `setTimeout` — same pattern as\n * `extra/resilience.ts` (spec §5.10 escape hatch documented on the class).\n */\n\nimport { ResettableTimer } from \"@graphrefly/pure-ts/core\";\nimport { fromAny } from \"@graphrefly/pure-ts/extra\";\nimport { firstValueFrom } from \"../../../../base/sources/settled.js\";\nimport { adapterWrapper, withLayer } from \"../_internal/wrappers.js\";\nimport type { LLMAdapter, LLMResponse, StreamDelta } from \"../core/types.js\";\n\nexport class LLMTimeoutError extends Error {\n\toverride name = \"LLMTimeoutError\";\n\tconstructor(public readonly ms: number) {\n\t\tsuper(`LLM call timed out after ${ms}ms`);\n\t}\n}\n\nexport function withLLMTimeout(inner: LLMAdapter, ms: number): LLMAdapter {\n\tif (ms <= 0) throw new RangeError(\"withLLMTimeout: ms must be > 0\");\n\n\tconst linkedSignal = (\n\t\tparent?: AbortSignal,\n\t): {\n\t\tsignal: AbortSignal;\n\t\tcancel: () => void;\n\t\t/** `true` once our timer fired — distinguishes our-timeout vs external abort. */\n\t\ttimedOut: () => boolean;\n\t} => {\n\t\tconst ac = new AbortController();\n\t\tlet timerFired = false;\n\t\tlet onParentAbort: (() => void) | undefined;\n\t\tconst timer = new ResettableTimer();\n\t\t// Cancel the timer synchronously when the parent aborts — otherwise a\n\t\t// parent-abort at `t = ms - ε` followed by our timer firing at\n\t\t// `t = ms` would set `timerFired = true`, causing\n\t\t// `convertAbortToTimeout` to incorrectly promote the user-initiated\n\t\t// abort to an `LLMTimeoutError`.\n\t\tif (parent) {\n\t\t\tif (parent.aborted) ac.abort(parent.reason);\n\t\t\telse {\n\t\t\t\tonParentAbort = () => {\n\t\t\t\t\ttimer.cancel();\n\t\t\t\t\tac.abort(parent.reason);\n\t\t\t\t};\n\t\t\t\tparent.addEventListener(\"abort\", onParentAbort, { once: true });\n\t\t\t}\n\t\t}\n\t\ttimer.start(ms, () => {\n\t\t\ttimerFired = true;\n\t\t\tac.abort(new LLMTimeoutError(ms));\n\t\t});\n\t\treturn {\n\t\t\tsignal: ac.signal,\n\t\t\tcancel: () => {\n\t\t\t\ttimer.cancel();\n\t\t\t\tif (parent && onParentAbort) parent.removeEventListener(\"abort\", onParentAbort);\n\t\t\t},\n\t\t\ttimedOut: () => timerFired,\n\t\t};\n\t};\n\n\t/**\n\t * When our own timer fired, real `fetch`/SDK adapters reject with\n\t * `AbortError`/DOMException regardless of `signal.reason`. We convert\n\t * that rejection into {@link LLMTimeoutError} so downstream predicates\n\t * (notably {@link defaultShouldRetry}) can distinguish \"we hit the\n\t * deadline\" from \"caller aborted us\" without relying on the adapter\n\t * preserving `signal.reason`.\n\t *\n\t * External aborts bubble through unchanged so caller-supplied\n\t * `invokeOpts.signal` still propagates as an abort.\n\t */\n\tconst convertAbortToTimeout = (err: unknown, timedOut: boolean): never => {\n\t\tif (!timedOut) throw err;\n\t\tif (err instanceof LLMTimeoutError) throw err;\n\t\tconst e = err as { name?: string; code?: string | number };\n\t\tconst isAbort =\n\t\t\te?.name === \"AbortError\" ||\n\t\t\t(e?.name === \"DOMException\" && Number(e.code) === 20) /* ABORT_ERR */ ||\n\t\t\t(err as Error)?.message === \"aborted\";\n\t\tif (isAbort) {\n\t\t\tconst timeout = new LLMTimeoutError(ms);\n\t\t\t(timeout as Error & { cause?: unknown }).cause = err;\n\t\t\tthrow timeout;\n\t\t}\n\t\tthrow err;\n\t};\n\n\tconst wrap = adapterWrapper(inner, {\n\t\tasync invoke(messages, invokeOpts): Promise<LLMResponse> {\n\t\t\tconst { signal, cancel, timedOut } = linkedSignal(invokeOpts?.signal);\n\t\t\ttry {\n\t\t\t\treturn await firstValueFrom(fromAny(inner.invoke(messages, { ...invokeOpts, signal })));\n\t\t\t} catch (err) {\n\t\t\t\treturn convertAbortToTimeout(err, timedOut());\n\t\t\t} finally {\n\t\t\t\tcancel();\n\t\t\t}\n\t\t},\n\n\t\tasync *stream(messages, invokeOpts): AsyncGenerator<StreamDelta> {\n\t\t\tconst { signal, cancel, timedOut } = linkedSignal(invokeOpts?.signal);\n\t\t\ttry {\n\t\t\t\tfor await (const d of inner.stream(messages, { ...invokeOpts, signal })) yield d;\n\t\t\t} catch (err) {\n\t\t\t\tconvertAbortToTimeout(err, timedOut());\n\t\t\t} finally {\n\t\t\t\tcancel();\n\t\t\t}\n\t\t},\n\t});\n\twithLayer(wrap, \"withLLMTimeout\", inner);\n\treturn wrap;\n}\n","/**\n * `resilientAdapter` — compose `withRateLimiter` + `withBudgetGate` +\n * `withLLMBreaker` + `withLLMTimeout` + `withRetry` + fallback over an {@link LLMAdapter}.\n *\n * Call-path peer of {@link resilientPipeline} (which operates on a reactive\n * `Node<T>` chain). Use `resilientPipeline` when composing graph sources; use\n * `resilientAdapter` when wrapping an adapter so downstream users see a\n * single hardened `invoke`/`stream` surface.\n *\n * Composition order (innermost to outermost, mirrors `resilientPipeline`):\n *\n * ```text\n * rateLimit → budget → breaker → timeout → retry → fallback\n * ```\n *\n * Rationale:\n * - **rateLimit innermost** — each attempt acquires a fresh slot; a retry\n * after a 429 waits for admission rather than bursting past the cap.\n * - **budget next** — per-attempt gate close short-circuits retries once a\n * cap trips.\n * - **breaker next** — each attempt observes circuit health; open breaker\n * fast-fails retries into fallback.\n * - **timeout before retry** — each retry re-arms a fresh per-attempt\n * deadline. If `timeout` wrapped `retry`, a single deadline would cover\n * the entire retry chain — surprising for callers.\n * - **retry before fallback** — fallback is entered only after the primary\n * exhausts its retry budget (or immediately fails in a way the predicate\n * doesn't retry).\n *\n * Every option is optional — omit the field and that layer is skipped. The\n * returned bundle exposes the primary adapter plus the internal bundles\n * (`rateLimiter`, `budget`, `breaker`) so callers can wire them into\n * dashboards, alerts, or `graphLens`.\n *\n * Fallback is implemented via {@link cascadingLlmAdapter}: when `fallback`\n * is provided, the wrapped primary adapter is placed at tier 0 and the\n * fallback adapter at tier 1. For N-tier cascades, use `cascadingLlmAdapter`\n * directly and wrap each tier with `resilientAdapter`.\n *\n * @module\n */\n\nimport type { AdaptiveRateLimiterBundle } from \"../../../resilience/adaptive-rate-limiter.js\";\nimport type { CircuitBreaker } from \"../../../resilience/breaker.js\";\nimport type { LLMAdapter } from \"../core/types.js\";\nimport type { CascadeExhaustionReport } from \"../routing/cascading.js\";\nimport { cascadingLlmAdapter } from \"../routing/cascading.js\";\nimport { type WithBreakerOptions, withLLMBreaker } from \"./breaker.js\";\nimport {\n\ttype LLMBudgetGateBundle,\n\ttype WithBudgetGateOptions,\n\twithBudgetGate,\n} from \"./budget-gate.js\";\nimport { type WithRateLimiterOptions, withRateLimiter } from \"./rate-limiter.js\";\nimport { type WithReplayCacheOptions, withReplayCache } from \"./replay-cache.js\";\nimport { type WithRetryOptions, withRetry } from \"./retry.js\";\nimport { withLLMTimeout } from \"./timeout.js\";\n\n/** Options for {@link resilientAdapter}. Every field is optional — omit to skip that layer. */\nexport interface ResilientAdapterOptions {\n\t/** Admission control. See {@link withRateLimiter}. */\n\trateLimit?: WithRateLimiterOptions;\n\t/** Cost/cap gate. See {@link withBudgetGate}. */\n\tbudget?: WithBudgetGateOptions;\n\t/** Circuit breaker. See {@link withBreaker}. */\n\tbreaker?: WithBreakerOptions;\n\t/** Per-attempt deadline in milliseconds. Omit to skip the timeout wrap. */\n\ttimeoutMs?: number;\n\t/** Retry policy on transient errors. See {@link withRetry}. */\n\tretry?: WithRetryOptions;\n\t/**\n\t * Fallback adapter engaged when the primary (post-retry) fails. Implemented\n\t * via {@link cascadingLlmAdapter} — the primary becomes tier 0, the\n\t * fallback becomes tier 1. For N-tier cascades, use `cascadingLlmAdapter`\n\t * directly and wrap each tier with `resilientAdapter` as needed.\n\t */\n\tfallback?: LLMAdapter;\n\t/** Name used as the primary tier name in the fallback cascade. Default `\"primary\"`. */\n\tname?: string;\n\t/**\n\t * Called when the cascade switches from one tier to the next after a\n\t * failure. Only fires when `fallback` is set. Threaded directly to the\n\t * inner {@link cascadingLlmAdapter}.\n\t */\n\tonFallback?: (from: string, to: string, error: unknown) => void;\n\t/**\n\t * Called when every tier in the cascade has been exhausted (all failed,\n\t * skipped by filter, or skipped by breaker). Only fires when `fallback`\n\t * is set. Threaded directly to the inner {@link cascadingLlmAdapter}.\n\t */\n\tonExhausted?: (report: CascadeExhaustionReport) => void;\n\t/**\n\t * Content-addressed replay cache wrapped OUTERMOST — a cache HIT short-\n\t * circuits the entire stack (rate-limit / budget / breaker / retry /\n\t * fallback), saving money and latency. Cache MISSes flow through the\n\t * normal stack; the successful result is stored on success. See\n\t * {@link withReplayCache}.\n\t */\n\tcache?: WithReplayCacheOptions;\n}\n\n/** Output bundle of {@link resilientAdapter}. */\nexport interface ResilientAdapterBundle {\n\t/** The final hardened adapter. */\n\tadapter: LLMAdapter;\n\t/** Rate-limiter internals (for dashboards). Present only when `opts.rateLimit` was set. */\n\trateLimiter?: AdaptiveRateLimiterBundle;\n\t/** Budget gate internals (for dashboards). Present only when `opts.budget` was set. */\n\tbudget?: LLMBudgetGateBundle;\n\t/** Circuit breaker (for dashboards). Present only when `opts.breaker` was set. */\n\tbreaker?: CircuitBreaker;\n}\n\n/**\n * Wrap `inner` with the standard resilience stack. See module docs for the\n * composition order and rationale.\n *\n * @example\n * ```ts\n * const { adapter, budget, breaker } = resilientAdapter(openai, {\n * rateLimit: { rpm: 60, tpm: 90_000 },\n * budget: { caps: { usd: 5 } },\n * breaker: { failureThreshold: 5, resetTimeoutMs: 30_000 },\n * timeoutMs: 30_000,\n * retry: { attempts: 3 },\n * fallback: webllm, // cascades to local on exhaustion\n * });\n *\n * // `adapter` is drop-in for anything expecting LLMAdapter.\n * // Subscribe to `budget.totals`, `breaker.state`, etc. for dashboards.\n * ```\n */\nexport function resilientAdapter(\n\tinner: LLMAdapter,\n\topts: ResilientAdapterOptions = {},\n): ResilientAdapterBundle {\n\tconst bundle: ResilientAdapterBundle = { adapter: inner };\n\tlet current: LLMAdapter = inner;\n\n\tif (opts.rateLimit) {\n\t\tconst wrapped = withRateLimiter(current, opts.rateLimit);\n\t\tcurrent = wrapped.adapter;\n\t\tbundle.rateLimiter = wrapped.limiter;\n\t}\n\tif (opts.budget) {\n\t\tconst wrapped = withBudgetGate(current, opts.budget);\n\t\tcurrent = wrapped.adapter;\n\t\tbundle.budget = wrapped.budget;\n\t}\n\tif (opts.breaker) {\n\t\tconst wrapped = withLLMBreaker(current, opts.breaker);\n\t\tcurrent = wrapped.adapter;\n\t\tbundle.breaker = wrapped.breaker;\n\t}\n\tif (opts.timeoutMs != null) {\n\t\tcurrent = withLLMTimeout(current, opts.timeoutMs);\n\t}\n\tif (opts.retry) {\n\t\tcurrent = withRetry(current, opts.retry);\n\t}\n\tif (opts.fallback) {\n\t\t// Secondary tier is named `\"fallback\"` internally; reject the same\n\t\t// label as the primary name so CascadeExhaustionReport.failed (a\n\t\t// Map keyed by tier name) and `resp.metadata.tier` stamping stay\n\t\t// unambiguous.\n\t\tif (opts.name === \"fallback\") {\n\t\t\tthrow new RangeError(\n\t\t\t\t'resilientAdapter: `name` cannot be \"fallback\" — collides with the secondary tier label.',\n\t\t\t);\n\t\t}\n\t\tconst cascadeOpts: {\n\t\t\tonFallback?: (from: string, to: string, error: unknown) => void;\n\t\t\tonExhausted?: (report: CascadeExhaustionReport) => void;\n\t\t} = {};\n\t\tif (opts.onFallback) cascadeOpts.onFallback = opts.onFallback;\n\t\tif (opts.onExhausted) cascadeOpts.onExhausted = opts.onExhausted;\n\t\tcurrent = cascadingLlmAdapter(\n\t\t\t[\n\t\t\t\t{ name: opts.name ?? \"primary\", adapter: current },\n\t\t\t\t{ name: \"fallback\", adapter: opts.fallback },\n\t\t\t],\n\t\t\tcascadeOpts,\n\t\t);\n\t}\n\tif (opts.cache) {\n\t\t// Outermost — a cache HIT skips the entire stack below.\n\t\tcurrent = withReplayCache(current, opts.cache);\n\t}\n\n\tbundle.adapter = current;\n\treturn bundle;\n}\n","/**\n * `frozenContext` — prefix-cache-friendly snapshot of upstream context.\n *\n * @module\n */\n\nimport { factoryTag, type Node, node as nodeFactory } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { aiMeta } from \"../_internal.js\";\n\nexport type FrozenContextOptions = {\n\t/**\n\t * Reactive signal that triggers re-materialization. Each `DATA` emission\n\t * from this node re-reads the source and refreshes the frozen value.\n\t * Typical shapes: `fromTimer(ms)` for periodic refresh, a stage-transition\n\t * node for event-driven refresh, or a manual `state<number>` the caller\n\t * increments via `setState(n + 1)`.\n\t *\n\t * When omitted, the frozen value is materialized exactly once (on first\n\t * subscribe) and never refreshes for the lifetime of the activation —\n\t * use this for session-start snapshots that must stay stable. The\n\t * single-shot latch IS reset on `INVALIDATE` (graph-wide flush via\n\t * `graph.signal([[INVALIDATE]])`), so callers who need an \"evict and\n\t * re-materialize\" escape hatch get one through the standard graph\n\t * lifecycle without having to wire a `refreshTrigger`.\n\t */\n\trefreshTrigger?: NodeInput<unknown>;\n\tname?: string;\n};\n\n/**\n * Freeze a reactive source into a stable snapshot that only re-materializes\n * on explicit trigger. Built for long-running harness loops where system\n * prompts include `agentMemory` / stage context — every reactive change to\n * the source invalidates the LLM provider's prefix cache, so re-rendering\n * the prompt every turn is expensive.\n *\n * `frozenContext(source)` reads the source once and caches the value;\n * downstream `promptNode` compositions see a stable reference until the\n * optional `refreshTrigger` fires.\n *\n * Trade-off: slightly stale context vs. prefix cache hit rate. For most\n * harness apps, the memory snapshot at session start is \"good enough\" —\n * refreshing on a coarse-grained trigger (`fromCron(\"*\\/30min\")`, stage\n * transition) preserves 90%+ prefix cache hits while keeping context useful.\n *\n * @example\n * ```ts\n * // Freeze agent memory for the duration of a stage.\n * const frozen = frozenContext(memory.context, {\n * refreshTrigger: stage, // re-materialize on stage change\n * });\n * const reply = promptNode({ context: frozen, ... });\n * ```\n *\n * @category patterns.ai\n */\nexport function frozenContext<T>(\n\tsource: NodeInput<T>,\n\topts?: FrozenContextOptions,\n): Node<T | null> {\n\tconst src = fromAny(source);\n\tconst trigger = opts?.refreshTrigger != null ? fromAny(opts.refreshTrigger) : null;\n\n\t// JSON-serializable subset of opts: omit `refreshTrigger` (a NodeInput).\n\tconst frozenArgs: Record<string, unknown> | undefined =\n\t\topts?.name !== undefined ? { name: opts.name } : undefined;\n\tconst frozenTag = factoryTag(\"frozenContext\", frozenArgs);\n\n\t// Single-shot path: deps = [src] only. Emit the first src value and then\n\t// hold regardless of source drift.\n\tif (trigger == null) {\n\t\treturn nodeFactory<T | null>(\n\t\t\t[src],\n\t\t\t(data, actions, ctx) => {\n\t\t\t\tconst alreadyEmitted = ctx.store.emitted === true;\n\t\t\t\tif (alreadyEmitted) return;\n\t\t\t\tconst srcBatch = data[0];\n\t\t\t\tconst srcValue =\n\t\t\t\t\tsrcBatch != null && srcBatch.length > 0 ? srcBatch.at(-1) : ctx.prevData[0];\n\t\t\t\t// Only emit once src has produced a settled value.\n\t\t\t\tif (srcValue === undefined) return;\n\t\t\t\tctx.store.emitted = true;\n\t\t\t\tactions.emit(srcValue as T);\n\t\t\t\t// On INVALIDATE (graph-wide flush), reset the \"already emitted\"\n\t\t\t\t// latch so the next fn re-run captures a fresh snapshot.\n\t\t\t\t// Without this, INVALIDATE clears the cache but the latch stays\n\t\t\t\t// armed, so subscribers stay on the cleared (null) state forever.\n\t\t\t\t//\n\t\t\t\t// Lock 6.D (Phase 13.6.B): clear `emitted` on deactivation —\n\t\t\t\t// the pre-flip auto-wipe handled this implicitly.\n\t\t\t\t//\n\t\t\t\t// QA D1 (Phase 13.6.B QA pass): `onResubscribableReset` covers\n\t\t\t\t// the multi-sub-stayed terminal-resubscribable path where\n\t\t\t\t// `_deactivate` does NOT run but the lifecycle reset still\n\t\t\t\t// needs to clear the latch. Without this slot, a sibling sink\n\t\t\t\t// that keeps the node alive past terminal would pin\n\t\t\t\t// `emitted === true` into the next subscription cycle and\n\t\t\t\t// suppress every future emission.\n\t\t\t\tconst store = ctx.store;\n\t\t\t\treturn {\n\t\t\t\t\tonInvalidate: () => {\n\t\t\t\t\t\tstore.emitted = false;\n\t\t\t\t\t},\n\t\t\t\t\tonDeactivation: () => {\n\t\t\t\t\t\tdelete store.emitted;\n\t\t\t\t\t},\n\t\t\t\t\tonResubscribableReset: () => {\n\t\t\t\t\t\tdelete store.emitted;\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: opts?.name ?? \"frozenContext\",\n\t\t\t\tdescribeKind: \"derived\",\n\t\t\t\tinitial: null,\n\t\t\t\tmeta: aiMeta(\"frozen_context\", { ...frozenTag }),\n\t\t\t},\n\t\t);\n\t}\n\n\t// Refresh-on-trigger path: deps = [src, trigger]. Emit the current src\n\t// value ONLY when the trigger dep is involved in the wave. Source-only\n\t// changes are silently held so downstream prompt composition sees the\n\t// same value between triggers, preserving the LLM provider's prefix cache.\n\t//\n\t// Uses raw `node()` to inspect per-dep wave involvement — `derived` fires\n\t// on any dep change and can't distinguish. The declaration-order semantic\n\t// gap in multi-dep push-on-subscribe (§2.7) works in our favor on\n\t// activation: src fires first (captured into ctx.prevData), trigger fires\n\t// in a second wave → emit via prevData[0] fallback.\n\treturn nodeFactory<T | null>(\n\t\t[src, trigger],\n\t\t(data, actions, ctx) => {\n\t\t\tconst triggerBatch = data[1];\n\t\t\tconst triggered = triggerBatch != null && triggerBatch.length > 0;\n\t\t\tif (!triggered) return;\n\t\t\tconst srcBatch = data[0];\n\t\t\tconst srcValue = srcBatch != null && srcBatch.length > 0 ? srcBatch.at(-1) : ctx.prevData[0];\n\t\t\tactions.emit(srcValue as T);\n\t\t},\n\t\t{\n\t\t\tname: opts?.name ?? \"frozenContext\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: null,\n\t\t\tmeta: aiMeta(\"frozen_context\", { ...frozenTag }),\n\t\t},\n\t);\n}\n","/**\n * `streamingPromptNode` + `gatedStream` — streaming LLM transforms.\n *\n * **Wave A Unit 2 rewrite:**\n * - `StreamChunk` retired. The live stream surface is now `deltaTopic:\n * TopicGraph<StreamDelta & {seq, ts}>` — every adapter delta (token,\n * thinking, tool-call, usage, finish) is published in order. The previous\n * shape retained the accumulated text per-chunk, producing O(N²) memory;\n * the new shape stores only per-delta payloads (O(N)).\n * - New `accumulatedText: Node<string>` on the bundle — lazy-built via\n * `ctx.store` over token-type deltas. Text-only extractors (`streamExtractor`,\n * `keywordFlagExtractor`, `toolCallExtractor`) consume this node.\n * - `retainedLimit?: number` option exposed for the delta topic (no default —\n * session scale is domain-specific per Unit 2 Q2).\n * - Unconditional `keepalive(output)` removed — callers subscribe as needed.\n * - System-prompt double-send fixed (matches promptNode Unit 1 fix).\n * - `format: \"json\"` throws on parse error with a content-preview diagnostic\n * (parity with `promptNode`).\n * - Shared body between `streamingPromptNode` and `gatedStream` extracted\n * into `streamingInvoke` per Unit 2 locked scope.\n *\n * @module\n */\n\nimport { batch, factoryTag, type Node, node, wallClockNs } from \"@graphrefly/pure-ts/core\";\nimport { filter, fromAny, keepalive, type NodeInput, switchMap } from \"@graphrefly/pure-ts/extra\";\nimport type { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { type TopicGraph, topic } from \"../../messaging/index.js\";\nimport { type GateController, type GateOptions, pipelineGraph } from \"../../orchestration/index.js\";\nimport { aiMeta, stripFences } from \"../_internal.js\";\nimport type { ChatMessage, LLMAdapter, StreamDelta } from \"../adapters/core/types.js\";\n\n/**\n * A single delta published to the `deltaTopic`. Every adapter emission is\n * forwarded — not just token deltas — so consumers see the full event log\n * (thinking, tool-call-delta, usage, finish).\n */\nexport type StampedDelta = StreamDelta & {\n\t/** Monotonic per-stream counter starting at 0. */\n\treadonly seq: number;\n\t/** Wall-clock nanoseconds at publish time (spec §5.11 central timer). */\n\treadonly ts: number;\n};\n\nexport type StreamingPromptNodeOptions = {\n\tname?: string;\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\t/** Output format — `\"json\"` attempts JSON.parse on accumulated text. Throws on parse failure. Default: `\"text\"`. */\n\tformat?: \"text\" | \"json\";\n\tsystemPrompt?: string;\n\tmeta?: Record<string, unknown>;\n\t/**\n\t * Optional retention cap on the delta topic. Omit for unbounded retention\n\t * (the topic grows until `dispose()`). Recommended values: `8_192` for\n\t * single-shot 8K-token responses, `1_000_000` for persistent session\n\t * topics, or explicit `dispose()` for worker-pool patterns.\n\t */\n\tretainedLimit?: number;\n};\n\n/**\n * Bundle returned by {@link streamingPromptNode}.\n */\nexport type StreamingPromptNodeHandle<T> = {\n\t/** Final parsed result (emits once per invocation, after stream completes). */\n\toutput: Node<T | null>;\n\t/** Live delta topic — every adapter delta in order, stamped with `seq` + `ts`. */\n\tdeltaTopic: TopicGraph<StampedDelta>;\n\t/**\n\t * Reactive accumulated-text view — lazy-built over `deltaTopic.latest`\n\t * filtered on `type === \"token\"`. Text-only extractors compose on this.\n\t * Emits the empty string before any token arrives.\n\t */\n\taccumulatedText: Node<string>;\n\t/** Tear down the delta topic and release resources. */\n\tdispose: () => void;\n};\n\n/**\n * Internal pump: open a stream against `adapter`, stamp each delta, publish\n * to `deltaTopic`, and return the final accumulated text. Extracted so\n * `gatedStream` can reuse the body (Unit 2 locked scope).\n */\nasync function streamingInvoke(\n\tadapter: LLMAdapter,\n\tmsgs: readonly ChatMessage[],\n\tinvokeOpts: {\n\t\tmodel?: string;\n\t\ttemperature?: number;\n\t\tmaxTokens?: number;\n\t\tsystemPrompt?: string;\n\t\tsignal: AbortSignal;\n\t},\n\tdeltaTopic: TopicGraph<StampedDelta>,\n): Promise<string> {\n\tlet accumulated = \"\";\n\tlet seq = 0;\n\tfor await (const delta of adapter.stream(msgs, invokeOpts)) {\n\t\tdeltaTopic.publish({ ...delta, seq: seq++, ts: wallClockNs() } as StampedDelta);\n\t\tif (delta.type === \"token\") accumulated += delta.delta;\n\t}\n\treturn accumulated;\n}\n\n/** Parse accumulated text per `format`. Throws on JSON parse failure. */\nfunction parseAccumulated<T>(accumulated: string, format: \"text\" | \"json\"): T | null {\n\tif (format === \"json\") {\n\t\ttry {\n\t\t\treturn JSON.parse(stripFences(accumulated)) as T;\n\t\t} catch (err) {\n\t\t\tconst preview = accumulated.slice(0, 160);\n\t\t\tthrow new Error(\n\t\t\t\t`streamingPromptNode: format:\"json\" — failed to parse accumulated text as JSON: ${(err as Error).message}; content preview: ${preview}`,\n\t\t\t);\n\t\t}\n\t}\n\treturn accumulated as unknown as T;\n}\n\n/**\n * Build the lazy `accumulatedText` derived that maintains a running string\n * over `deltaTopic.latest` filtered on token deltas. Uses `ctx.store` per\n * COMPOSITION-GUIDE §20 — accumulator clears on deactivation.\n */\nfunction makeAccumulatedText(deltaTopic: TopicGraph<StampedDelta>, name: string): Node<string> {\n\t// Lock 6.D (Phase 13.6.B): clear acc on deactivation so a resubscribed\n\t// accumulator starts fresh. Pre-flip this came for free via\n\t// `_deactivate`'s store wipe.\n\tlet cleanup: { onDeactivation: () => void } | undefined;\n\treturn node<string>(\n\t\t[deltaTopic.latest],\n\t\t(batchData, actions, ctx) => {\n\t\t\tif (cleanup === undefined) {\n\t\t\t\tconst store = ctx.store;\n\t\t\t\tcleanup = {\n\t\t\t\t\tonDeactivation: () => {\n\t\t\t\t\t\tdelete store.acc;\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\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 d = data[0];\n\t\t\tconst store = ctx.store as { acc?: string };\n\t\t\tif (d === undefined) {\n\t\t\t\tactions.emit(store.acc ?? \"\");\n\t\t\t\treturn cleanup;\n\t\t\t}\n\t\t\tconst delta = d as StampedDelta;\n\t\t\t// `seq === 0` marks the first delta of a fresh invocation — reset\n\t\t\t// the accumulator so runs don't concatenate across switchMap\n\t\t\t// supersedes. Without this, invocation 2's text would be appended\n\t\t\t// to invocation 1's text (the `deltaTopic` outlives each switchMap\n\t\t\t// inner, so `ctx.store.acc` would otherwise persist).\n\t\t\tif (delta.seq === 0) store.acc = \"\";\n\t\t\tif (delta.type === \"token\") {\n\t\t\t\tstore.acc = (store.acc ?? \"\") + delta.delta;\n\t\t\t}\n\t\t\tactions.emit(store.acc ?? \"\");\n\t\t\treturn cleanup;\n\t\t},\n\t\t{\n\t\t\tname,\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: aiMeta(\"accumulated_text\"),\n\t\t\tinitial: \"\",\n\t\t},\n\t);\n}\n\n/**\n * Streaming LLM transform: wraps a prompt template + adapter into a reactive\n * streaming pipeline. Re-invokes the LLM whenever any dep changes; the\n * previous in-flight stream is canceled automatically via `switchMap`.\n *\n * Every adapter delta is published to `deltaTopic` stamped with `seq` + `ts`.\n * Text consumers subscribe to `accumulatedText` (auto-maintained). Delta-\n * specific consumers (`costMeterExtractor` on `usage` deltas) subscribe to\n * `deltaTopic` directly and filter by `delta.type`.\n *\n * The async boundary is handled by `fromAny(asyncGenerator)` (spec §5.10).\n */\nexport function streamingPromptNode<T = string>(\n\tadapter: LLMAdapter,\n\tdeps: readonly Node<unknown>[],\n\tprompt: string | ((...depValues: unknown[]) => string),\n\topts?: StreamingPromptNodeOptions,\n): StreamingPromptNodeHandle<T> {\n\tconst sourceName = opts?.name ?? \"llm\";\n\tconst format = opts?.format ?? \"text\";\n\tconst deltaTopic = topic<StampedDelta>(`${sourceName}/stream`, {\n\t\t...(opts?.retainedLimit != null ? { retainedLimit: opts.retainedLimit } : {}),\n\t});\n\n\tconst messagesNode = node<readonly ChatMessage[]>(\n\t\tdeps as Node<unknown>[],\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\tif (data.some((v) => v == null)) {\n\t\t\t\tactions.emit([]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst text = typeof prompt === \"string\" ? prompt : prompt(...data);\n\t\t\tif (!text) {\n\t\t\t\tactions.emit([]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tactions.emit([{ role: \"user\", content: text }]);\n\t\t},\n\t\t{\n\t\t\tname: `${sourceName}::messages`,\n\t\t\tmeta: aiMeta(\"prompt_node::messages\"),\n\t\t\tinitial: [] as readonly ChatMessage[],\n\t\t},\n\t);\n\n\tconst output = switchMap(\n\t\tmessagesNode,\n\t\t(msgs) => {\n\t\t\tconst chatMsgs = msgs as readonly ChatMessage[];\n\t\t\tif (!chatMsgs || chatMsgs.length === 0) {\n\t\t\t\treturn node<T | null>([], { initial: null }) as NodeInput<T | null>;\n\t\t\t}\n\t\t\tconst ac = new AbortController();\n\t\t\tasync function* pumpAndCollect(): AsyncGenerator<T | null> {\n\t\t\t\ttry {\n\t\t\t\t\tconst accumulated = await streamingInvoke(\n\t\t\t\t\t\tadapter,\n\t\t\t\t\t\tchatMsgs,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmodel: opts?.model,\n\t\t\t\t\t\t\ttemperature: opts?.temperature,\n\t\t\t\t\t\t\tmaxTokens: opts?.maxTokens,\n\t\t\t\t\t\t\tsystemPrompt: opts?.systemPrompt,\n\t\t\t\t\t\t\tsignal: ac.signal,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdeltaTopic,\n\t\t\t\t\t);\n\t\t\t\t\tyield parseAccumulated<T>(accumulated, format);\n\t\t\t\t} finally {\n\t\t\t\t\tac.abort();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fromAny(pumpAndCollect());\n\t\t},\n\t\t{ meta: factoryTag(\"streamingPromptNode\") },\n\t);\n\n\tconst accumulatedText = makeAccumulatedText(deltaTopic, `${sourceName}::accumulatedText`);\n\n\t// Keepalive on `output` — a caller who subscribes ONLY to `deltaTopic` or\n\t// `accumulatedText` expects the stream to run (that's the bundle contract\n\t// — three reactive surfaces, any one of them activates the pipeline).\n\t// Without this, the lazy `switchMap` stays cold until someone subscribes\n\t// to `.output` directly, and deltas never flow. The original\n\t// `streamingPromptNode` carried this keepalive; the Unit 2 \"zero overhead\n\t// if nobody subscribes\" removal broke the bundle-activation contract.\n\t// Restored here with explicit dispose so the keepalive follows the bundle.\n\tconst unsubOutput = keepalive(output);\n\n\treturn {\n\t\toutput,\n\t\tdeltaTopic,\n\t\taccumulatedText,\n\t\tdispose: () => {\n\t\t\tunsubOutput();\n\t\t\tdeltaTopic.destroy();\n\t\t},\n\t};\n}\n\nexport type GatedStreamOptions = StreamingPromptNodeOptions & {\n\t/** Gate options (maxPending, startOpen). */\n\tgate?: Omit<GateOptions, \"meta\">;\n};\n\n/**\n * Bundle returned by {@link gatedStream}.\n */\nexport type GatedStreamHandle<T> = {\n\t/** Final parsed result (after gate approval). */\n\toutput: Node<T | null>;\n\t/** Live delta topic — every adapter delta in order, stamped with `seq` + `ts`. */\n\tdeltaTopic: TopicGraph<StampedDelta>;\n\t/** Reactive accumulated-text view. */\n\taccumulatedText: Node<string>;\n\t/**\n\t * Gate controller — approve, reject (aborts in-flight stream), modify.\n\t * The gate's DATA domain is `T` (not `T | null`): the pre-gate `filter`\n\t * drops nulls, so the pending queue never holds a null. The controller's\n\t * `node` output type stays `T | null` only because `gate.approve()` on an\n\t * empty queue would surface `null` — callers should treat `null` as \"no\n\t * value\" rather than as a modeled null signal.\n\t */\n\tgate: GateController<T>;\n\t/** Tear down the delta topic + gate keepalive. */\n\tdispose: () => void;\n};\n\n/**\n * Streaming LLM transform with human-in-the-loop gate integration.\n *\n * Composes {@link streamingPromptNode} with `gate` so that:\n * - `gate.reject()` discards the pending value **and** aborts the in-flight\n * stream (toggles an internal cancel signal → switchMap restart → abort).\n * - `gate.modify()` transforms the pending value before forwarding downstream.\n * - `gate.approve()` forwards the final result as normal.\n *\n * Wave A Unit 2 defers full `gatedStream` review to Wave B Unit 17 (the\n * `gate()` primitive itself is reviewed there). This implementation retains\n * the existing gate API while adopting the Unit 2 delta-topic shape.\n */\nexport function gatedStream<T = string>(\n\tgraph: Graph,\n\tname: string,\n\tadapter: LLMAdapter,\n\tdeps: readonly Node<unknown>[],\n\tprompt: string | ((...depValues: unknown[]) => string),\n\topts?: GatedStreamOptions,\n): GatedStreamHandle<T> {\n\tconst cancelSignal = node<number>([], { name: `${name}/cancel`, initial: 0 });\n\tlet cancelCounter = 0;\n\n\tconst allDeps = [...deps, cancelSignal] as readonly Node<unknown>[];\n\n\tconst sourceName = opts?.name ?? name;\n\tconst format = opts?.format ?? \"text\";\n\tconst deltaTopic = topic<StampedDelta>(`${sourceName}/stream`, {\n\t\t...(opts?.retainedLimit != null ? { retainedLimit: opts.retainedLimit } : {}),\n\t});\n\n\tconst messagesNode = node<readonly ChatMessage[]>(\n\t\tallDeps as Node<unknown>[],\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\t// Last dep is the cancel signal — exclude from prompt args.\n\t\t\tconst depValues = data.slice(0, -1);\n\t\t\tif (depValues.some((v) => v == null)) {\n\t\t\t\tactions.emit([]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst text = typeof prompt === \"string\" ? prompt : prompt(...depValues);\n\t\t\tif (!text) {\n\t\t\t\tactions.emit([]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tactions.emit([{ role: \"user\", content: text }]);\n\t\t},\n\t\t{\n\t\t\tname: `${sourceName}::messages`,\n\t\t\tmeta: aiMeta(\"prompt_node::messages\"),\n\t\t\tinitial: [] as readonly ChatMessage[],\n\t\t},\n\t);\n\n\tconst output = switchMap(\n\t\tmessagesNode,\n\t\t(msgs) => {\n\t\t\tconst chatMsgs = msgs as readonly ChatMessage[];\n\t\t\tif (!chatMsgs || chatMsgs.length === 0) {\n\t\t\t\treturn node<T | null>([], { initial: null }) as NodeInput<T | null>;\n\t\t\t}\n\t\t\tconst ac = new AbortController();\n\t\t\tasync function* pumpAndCollect(): AsyncGenerator<T | null> {\n\t\t\t\ttry {\n\t\t\t\t\tconst accumulated = await streamingInvoke(\n\t\t\t\t\t\tadapter,\n\t\t\t\t\t\tchatMsgs,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmodel: opts?.model,\n\t\t\t\t\t\t\ttemperature: opts?.temperature,\n\t\t\t\t\t\t\tmaxTokens: opts?.maxTokens,\n\t\t\t\t\t\t\tsystemPrompt: opts?.systemPrompt,\n\t\t\t\t\t\t\tsignal: ac.signal,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdeltaTopic,\n\t\t\t\t\t);\n\t\t\t\t\tyield parseAccumulated<T>(accumulated, format);\n\t\t\t\t} finally {\n\t\t\t\t\tac.abort();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fromAny(pumpAndCollect());\n\t\t},\n\t\t{ meta: factoryTag(\"gatedStream\") },\n\t);\n\n\tconst accumulatedText = makeAccumulatedText(deltaTopic, `${sourceName}::accumulatedText`);\n\n\t// Filter out null stream results so the gate only sees real values. Using\n\t// `filter()` (not a `derived` with `return undefined`) is load-bearing:\n\t// `derived`'s wrapper always calls `actions.emit(fn(data))`, so returning\n\t// `undefined` would still emit `DATA(undefined)` into the gate's pending\n\t// queue — approve/modify would then surface `undefined` to downstream\n\t// consumers. `filter` propagates RESOLVED for falsey matches, keeping the\n\t// queue clean. (This was the second half of the gatedStream activation\n\t// fix — the first was keepalive-ing `gateCtrl.output`.)\n\tconst nonNullOutput = filter<T | null>(output, (v) => v != null) as Node<T>;\n\tgraph.add(nonNullOutput, { name: `${name}/raw` });\n\n\t// Wire gate on the output. Type parameter is `T` (not `T | null`) — the\n\t// `filter` above drops nulls before they reach the gate, so the pending\n\t// queue's DATA domain is `T` only.\n\t//\n\t// C3 — `nonNullOutput` is owned by the parent `graph`. Pass it as a Node\n\t// ref to `approvalGate`; the gate's foreign-source path wraps it in a\n\t// local proxy derived registered under `${name}/gate/source` inside\n\t// gateSubgraph. The dual-add pattern (`graph.add` + `gateSubgraph.add`)\n\t// is retired — Session B.1's \"no wrapper\" invariant gave way to the\n\t// single-owner invariant per the C3 lock.\n\tconst gateSubgraph = pipelineGraph(`${name}/gate-graph`);\n\tgraph.mount(`${name}/gate-graph`, gateSubgraph);\n\tconst gateCtrl = gateSubgraph.approvalGate<T>(\n\t\t`${name}/gate`,\n\t\tnonNullOutput as Node<unknown>,\n\t\topts?.gate,\n\t);\n\n\t// Keepalive the switchMap product, the gate's output node, AND the\n\t// accumulator so the full bundle contract (\"three reactive surfaces, any\n\t// one activates the pipeline\") holds:\n\t//\n\t// - `keepalive(output)` activates the streaming switchMap so the adapter\n\t// generator runs even before a downstream subscriber attaches.\n\t// - `keepalive(gateCtrl.output)` activates the gate's fn body — which is\n\t// what writes into the internal `pending` queue. Without it, a caller\n\t// that only subscribes to `gate.count` / `gate.pending` / `deltaTopic`\n\t// (but not `gate.output`) would see `count` stuck at 0 indefinitely:\n\t// stream values reach the gate's input but the gate's fn never runs.\n\t// - `keepalive(accumulatedText)` ensures `.cache` reflects the running\n\t// total for callers that read the accumulator as a snapshot instead of\n\t// subscribing to it.\n\t//\n\t// Dropping any of the three surfaces as a silent stall in `ai.test.ts`'s\n\t// gatedStream suite.\n\t//\n\t// All three unsubs are also registered with the host graph so\n\t// `parent.destroy()` reclaims them even if the caller forgets to call\n\t// `dispose()`. `dispose()` itself runs them eagerly for prompt teardown.\n\tconst unsubOutput = keepalive(output);\n\tconst unsubGate = keepalive(gateCtrl.output);\n\tconst unsubAccumulated = keepalive(accumulatedText);\n\tgraph.addDisposer(unsubOutput);\n\tgraph.addDisposer(unsubGate);\n\tgraph.addDisposer(unsubAccumulated);\n\n\t// Wrap reject to also abort the in-flight stream. Both mutations happen\n\t// inside `batch()` so downstream subscribers never observe a torn state\n\t// where `gate.count` has decremented but `cancelSignal` hasn't yet\n\t// advanced (spec §2 two-phase DIRTY-before-DATA atomicity).\n\tconst originalReject = gateCtrl.reject.bind(gateCtrl);\n\tconst gateWithAbort: GateController<T> = {\n\t\t...gateCtrl,\n\t\treject(count = 1) {\n\t\t\tbatch(() => {\n\t\t\t\toriginalReject(count);\n\t\t\t\tcancelSignal.emit(++cancelCounter);\n\t\t\t});\n\t\t},\n\t};\n\n\treturn {\n\t\toutput: gateCtrl.output,\n\t\tdeltaTopic,\n\t\taccumulatedText,\n\t\tgate: gateWithAbort,\n\t\tdispose: () => {\n\t\t\tunsubOutput();\n\t\t\tunsubGate();\n\t\t\tunsubAccumulated();\n\t\t\tdeltaTopic.destroy();\n\t\t},\n\t};\n}\n","/**\n * `systemPromptBuilder` — assembles a reactive system prompt from sections.\n *\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\n\nimport { fromAny, keepalive, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { aiMeta } from \"../_internal.js\";\n\n/**\n * Assembles a system prompt from reactive sections. Each section is a\n * `NodeInput<string>` — the prompt updates when any section changes.\n */\nexport type SystemPromptHandle = Node<string> & { dispose: () => void };\n\nexport function systemPromptBuilder(\n\tsections: readonly NodeInput<string>[],\n\topts?: { separator?: string; name?: string },\n): SystemPromptHandle {\n\tconst separator = opts?.separator ?? \"\\n\\n\";\n\tconst sectionNodes = sections.map((s) =>\n\t\ttypeof s === \"string\" ? node([], { initial: s }) : fromAny(s),\n\t);\n\tconst prompt = node(\n\t\tsectionNodes,\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\tactions.emit((data as string[]).filter((v) => v != null && v !== \"\").join(separator));\n\t\t},\n\t\t{\n\t\t\tname: opts?.name ?? \"systemPrompt\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: aiMeta(\"system_prompt\"),\n\t\t\tinitial: \"\",\n\t\t},\n\t);\n\tconst unsub = keepalive(prompt);\n\treturn Object.assign(prompt, { dispose: unsub });\n}\n","/**\n * Cost meter extractor — derives live cost readings from the delta topic.\n *\n * **Wave A Unit 3 rewrite:** signature takes `deltaTopic: TopicGraph<StampedDelta>`\n * instead of the old `TopicGraph<StreamChunk>`. The meter prefers real\n * `usage` deltas from the adapter; when no `usage` has been seen yet it\n * falls back to a char-based estimate over token deltas and stamps\n * `estimated: true` on the reading. Chunk count is the count of\n * token-type deltas seen (was `chunk.index + 1`).\n *\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\nimport type { TopicGraph } from \"../../messaging/index.js\";\nimport { aiMeta } from \"../_internal.js\";\nimport { sumInputTokens, sumOutputTokens } from \"../adapters/core/types.js\";\nimport type { StampedDelta } from \"../prompts/streaming.js\";\n\n/** A cost meter reading from the stream. */\nexport type CostMeterReading = {\n\treadonly chunkCount: number;\n\treadonly charCount: number;\n\treadonly estimatedTokens: number;\n\t/**\n\t * `true` when no adapter `usage` delta has been observed yet —\n\t * `estimatedTokens` is a char-based heuristic and should be treated as an\n\t * approximation. Flips to `false` once a real `usage` delta arrives.\n\t */\n\treadonly estimated: boolean;\n};\n\nexport type CostMeterOptions = {\n\t/** Characters per token approximation. Default: 4 (GPT-family). */\n\tcharsPerToken?: number;\n\tname?: string;\n};\n\nconst costMeterEqual = (a: CostMeterReading, b: CostMeterReading): boolean => {\n\tif (a === b) return true;\n\treturn (\n\t\ta.chunkCount === b.chunkCount &&\n\t\ta.charCount === b.charCount &&\n\t\ta.estimatedTokens === b.estimatedTokens &&\n\t\ta.estimated === b.estimated\n\t);\n};\n\n/**\n * Mounts a cost meter on the delta topic. Prefers real `usage` deltas from\n * the provider; falls back to char-based estimation on token deltas alone\n * (with `meta.estimated: true` on the reading).\n *\n * Default structural equals suppresses DATA emission when two consecutive\n * readings are identical.\n */\nexport function costMeterExtractor(\n\tdeltaTopic: TopicGraph<StampedDelta>,\n\topts?: CostMeterOptions,\n): Node<CostMeterReading> {\n\tconst charsPerToken = opts?.charsPerToken ?? 4;\n\tconst ZERO: CostMeterReading = {\n\t\tchunkCount: 0,\n\t\tcharCount: 0,\n\t\testimatedTokens: 0,\n\t\testimated: true,\n\t};\n\t// Lock 6.D (Phase 13.6.B): clear per-stream counters on deactivation\n\t// so a resubscribed cost meter starts at zero on the next cycle.\n\tlet cleanup: { onDeactivation: () => void } | undefined;\n\treturn node<CostMeterReading>(\n\t\t[deltaTopic.latest],\n\t\t(batchData, actions, ctx) => {\n\t\t\tif (cleanup === undefined) {\n\t\t\t\tconst store = ctx.store;\n\t\t\t\tcleanup = {\n\t\t\t\t\tonDeactivation: () => {\n\t\t\t\t\t\tdelete store.chunkCount;\n\t\t\t\t\t\tdelete store.charCount;\n\t\t\t\t\t\tdelete store.usageTokens;\n\t\t\t\t\t\tdelete store.sawUsage;\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\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 d = data[0];\n\t\t\tif (d === undefined) {\n\t\t\t\tactions.emit(ZERO);\n\t\t\t\treturn cleanup;\n\t\t\t}\n\t\t\tconst delta = d as StampedDelta;\n\n\t\t\tif (!(\"chunkCount\" in ctx.store)) {\n\t\t\t\tctx.store.chunkCount = 0;\n\t\t\t\tctx.store.charCount = 0;\n\t\t\t\tctx.store.usageTokens = 0;\n\t\t\t\tctx.store.sawUsage = false;\n\t\t\t}\n\t\t\tconst store = ctx.store as {\n\t\t\t\tchunkCount: number;\n\t\t\t\tcharCount: number;\n\t\t\t\tusageTokens: number;\n\t\t\t\tsawUsage: boolean;\n\t\t\t};\n\n\t\t\tif (delta.type === \"token\") {\n\t\t\t\tstore.chunkCount += 1;\n\t\t\t\tstore.charCount += delta.delta.length;\n\t\t\t} else if (delta.type === \"usage\") {\n\t\t\t\tstore.sawUsage = true;\n\t\t\t\tstore.usageTokens = sumInputTokens(delta.usage) + sumOutputTokens(delta.usage);\n\t\t\t}\n\n\t\t\tconst estimatedTokens = store.sawUsage\n\t\t\t\t? store.usageTokens\n\t\t\t\t: Math.ceil(store.charCount / charsPerToken);\n\t\t\tactions.emit({\n\t\t\t\tchunkCount: store.chunkCount,\n\t\t\t\tcharCount: store.charCount,\n\t\t\t\testimatedTokens,\n\t\t\t\testimated: !store.sawUsage,\n\t\t\t});\n\t\t\treturn cleanup;\n\t\t},\n\t\t{\n\t\t\tname: opts?.name ?? \"cost-meter\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: ZERO,\n\t\t\tmeta: aiMeta(\"cost_meter_extractor\"),\n\t\t\tequals: costMeterEqual,\n\t\t},\n\t);\n}\n","/**\n * Keyword-flag extractor — scans accumulated stream text for configured patterns.\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { aiMeta } from \"../_internal.js\";\n\n/** A keyword match detected in the stream. */\nexport type KeywordFlag = {\n\treadonly label: string;\n\treadonly pattern: RegExp;\n\treadonly match: string;\n\treadonly position: number;\n};\n\nexport type KeywordFlagExtractorOptions = {\n\tpatterns: readonly { pattern: RegExp; label: string }[];\n\tname?: string;\n\t/**\n\t * Maximum length of any pattern's literal text. Used as an overlap window\n\t * when cursoring through the accumulated stream so matches that span\n\t * chunk boundaries aren't missed. Default: 128.\n\t */\n\tmaxPatternLength?: number;\n};\n\nconst keywordFlagsEqual = (\n\ta: readonly KeywordFlag[] | null,\n\tb: readonly KeywordFlag[] | null,\n): boolean => {\n\tif (a === b) return true;\n\tif (a == null || b == null) return a === b;\n\tif (a.length !== b.length) return false;\n\tfor (let i = 0; i < a.length; i++) {\n\t\tconst x = a[i];\n\t\tconst y = b[i];\n\t\tif (\n\t\t\tx.label !== y.label ||\n\t\t\tx.pattern !== y.pattern ||\n\t\t\tx.match !== y.match ||\n\t\t\tx.position !== y.position\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n};\n\n/**\n * Mounts a keyword-flag extractor on accumulated text. Scans for all\n * configured patterns and emits an array of matches.\n *\n * **Wave A Unit 3 rewrite:** signature takes `accumulatedText: Node<string>`\n * instead of the old `TopicGraph<StreamChunk>`. Patterns are compiled once\n * at factory time (was per-chunk). `maxPatternLength` is validated at\n * factory time — any pattern whose source exceeds the window throws\n * immediately.\n *\n * Use cases: design invariant violations (`setTimeout`, `EventEmitter`), PII\n * detection (SSN, email, phone), toxicity keywords, off-track reasoning.\n *\n * **Streaming optimization.** Maintains a cursor across waves in `ctx.store`\n * so each emission scans only the delta region `accumulated.slice(scannedTo -\n * maxPatternLength)` — not the full string. Reactivation clears `ctx.store`\n * and resumes from offset 0 (COMPOSITION-GUIDE §20 RAM semantics).\n *\n * Default structural equals suppresses DATA emission when no new flags were\n * found this wave.\n */\nexport function keywordFlagExtractor(\n\taccumulatedText: Node<string>,\n\topts: KeywordFlagExtractorOptions,\n): Node<readonly KeywordFlag[]> {\n\tconst maxPatternLength = opts.maxPatternLength ?? 128;\n\t// Factory-time: validate pattern literal lengths + compile once.\n\tfor (const p of opts.patterns) {\n\t\tif (p.pattern.source.length > maxPatternLength) {\n\t\t\tthrow new Error(\n\t\t\t\t`keywordFlagExtractor: pattern \"${p.label}\" literal exceeds maxPatternLength (${p.pattern.source.length} > ${maxPatternLength}); raise the option or shorten the pattern.`,\n\t\t\t);\n\t\t}\n\t}\n\tconst compiled = opts.patterns.map((p) => ({\n\t\tlabel: p.label,\n\t\tpattern: p.pattern,\n\t\tcompiled: new RegExp(p.pattern.source, `${p.pattern.flags.replace(\"g\", \"\")}g`),\n\t}));\n\t// Lock 6.D (Phase 13.6.B): clear scan state on deactivation so a\n\t// resubscribed extractor doesn't carry over per-stream cursors.\n\tlet cleanup: { onDeactivation: () => void } | undefined;\n\treturn node<readonly KeywordFlag[]>(\n\t\t[accumulatedText],\n\t\t(batchData, actions, ctx) => {\n\t\t\tif (cleanup === undefined) {\n\t\t\t\tconst store = ctx.store;\n\t\t\t\tcleanup = {\n\t\t\t\t\tonDeactivation: () => {\n\t\t\t\t\t\tdelete store.flags;\n\t\t\t\t\t\tdelete store.scannedTo;\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\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 text = data[0];\n\t\t\tif (text == null) {\n\t\t\t\tactions.emit([]);\n\t\t\t\treturn cleanup;\n\t\t\t}\n\t\t\tconst accumulated = text as string;\n\n\t\t\tif (!(\"flags\" in ctx.store)) {\n\t\t\t\tctx.store.flags = [] as KeywordFlag[];\n\t\t\t\tctx.store.scannedTo = 0;\n\t\t\t}\n\t\t\tconst flags = ctx.store.flags as KeywordFlag[];\n\t\t\tconst scannedTo = ctx.store.scannedTo as number;\n\n\t\t\t// Scan the delta plus an overlap window so matches that span\n\t\t\t// chunk boundaries (e.g. \"EventE\" + \"mitter\") are still found.\n\t\t\tconst startOffset = Math.max(0, scannedTo - maxPatternLength);\n\t\t\tconst region = accumulated.slice(startOffset);\n\t\t\tlet added = false;\n\t\t\tfor (const { pattern, label, compiled: re } of compiled) {\n\t\t\t\tre.lastIndex = 0;\n\t\t\t\tfor (const m of region.matchAll(re)) {\n\t\t\t\t\tconst pos = startOffset + (m.index ?? 0);\n\t\t\t\t\tif (pos + m[0].length <= scannedTo) continue;\n\t\t\t\t\tflags.push({ label, pattern, match: m[0], position: pos });\n\t\t\t\t\tadded = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tctx.store.scannedTo = accumulated.length;\n\t\t\tactions.emit(added ? [...flags] : flags.slice());\n\t\t\treturn cleanup;\n\t\t},\n\t\t{\n\t\t\tname: opts.name ?? \"keyword-flag-extractor\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: [],\n\t\t\tmeta: aiMeta(\"keyword_flag_extractor\"),\n\t\t\tequals: keywordFlagsEqual,\n\t\t},\n\t);\n}\n","/**\n * Generic stream extractor — mounts an extract function on accumulated text.\n *\n * **Wave A Unit 3 rewrite:** signature changed from\n * `streamExtractor(topic: TopicGraph<StreamChunk>, fn)` to\n * `streamExtractor(accumulatedText: Node<string>, fn)`. The Unit 2 delta-\n * topic redesign removed the per-chunk `accumulated` field; callers pass\n * `streamingPromptNode(...).accumulatedText` (or any other `Node<string>`\n * source of accumulated text). Source-agnostic — the extractor doesn't care\n * whether the text came from an LLM, WebSocket, SSE tail, or file reader.\n *\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { aiMeta } from \"../_internal.js\";\n\n/**\n * Mounts an extractor function on a reactive accumulated-text source. Returns\n * a derived node that emits extracted values as the text grows.\n *\n * @param accumulatedText - Reactive `Node<string>` of accumulated text.\n * @param extractFn - `(accumulated: string) => T | null`.\n * @param opts - Optional name + structural equals.\n * @returns Derived node emitting extracted values.\n */\nexport function streamExtractor<T>(\n\taccumulatedText: Node<string>,\n\textractFn: (accumulated: string) => T | null,\n\topts?: {\n\t\tname?: string;\n\t\t/**\n\t\t * Optional structural equals for the extractor output. When two\n\t\t * consecutive chunks produce structurally-equal outputs, the framework\n\t\t * emits `RESOLVED` instead of `DATA`, saving downstream work. Default:\n\t\t * reference equality (`Object.is`). The library cannot know your\n\t\t * output shape — supply this when your `extractFn` returns structured\n\t\t * objects or arrays.\n\t\t */\n\t\tequals?: (a: T | null, b: T | null) => boolean;\n\t},\n): Node<T | null> {\n\treturn node<T | null>(\n\t\t[accumulatedText],\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 text = data[0];\n\t\t\tactions.emit(text == null ? null : extractFn(text as string));\n\t\t},\n\t\t{\n\t\t\tname: opts?.name ?? \"extractor\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: null,\n\t\t\tmeta: aiMeta(\"stream_extractor\"),\n\t\t\t...(opts?.equals ? { equals: opts.equals } : {}),\n\t\t},\n\t);\n}\n","/**\n * Tool-call extractor — scans accumulated stream text for complete JSON tool call objects.\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { aiMeta } from \"../_internal.js\";\n\n/** A tool call detected in the stream. */\nexport type ExtractedToolCall = {\n\treadonly name: string;\n\treadonly arguments: Record<string, unknown>;\n\treadonly raw: string;\n\treadonly startIndex: number;\n};\n\nconst toolCallsEqual = (\n\ta: readonly ExtractedToolCall[] | null,\n\tb: readonly ExtractedToolCall[] | null,\n): boolean => {\n\tif (a === b) return true;\n\tif (a == null || b == null) return a === b;\n\tif (a.length !== b.length) return false;\n\tfor (let i = 0; i < a.length; i++) {\n\t\tconst x = a[i];\n\t\tconst y = b[i];\n\t\tif (x.startIndex !== y.startIndex || x.name !== y.name || x.raw !== y.raw) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n};\n\n/**\n * Mounts a tool-call extractor on a streaming topic. Scans accumulated text\n * for complete JSON objects containing `\"name\"` and `\"arguments\"` keys (the\n * standard tool_call shape). Partial JSON is ignored until the closing brace.\n *\n * Feeds into the tool interception chain for reactive tool gating mid-stream.\n *\n * **Streaming optimization.** Maintains a cursor (`scanFrom`) in `ctx.store`\n * so each chunk resumes brace-scanning from the position after the last\n * complete parse (or the last incomplete open brace). Already-parsed objects\n * are not re-parsed. Default structural equals suppresses DATA emission when\n * no new tool call completed this chunk.\n */\nexport function toolCallExtractor(\n\taccumulatedText: Node<string>,\n\topts?: { name?: string },\n): Node<readonly ExtractedToolCall[]> {\n\t// Lock 6.D (Phase 13.6.B): clear scan state on deactivation so a\n\t// resubscribed extractor doesn't ship stale per-stream cursors.\n\tlet cleanup: { onDeactivation: () => void } | undefined;\n\treturn node<readonly ExtractedToolCall[]>(\n\t\t[accumulatedText],\n\t\t(batchData, actions, ctx) => {\n\t\t\tif (cleanup === undefined) {\n\t\t\t\tconst store = ctx.store;\n\t\t\t\tcleanup = {\n\t\t\t\t\tonDeactivation: () => {\n\t\t\t\t\t\tdelete store.calls;\n\t\t\t\t\t\tdelete store.scanFrom;\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\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 text = data[0];\n\t\t\tif (text == null) {\n\t\t\t\tactions.emit([]);\n\t\t\t\treturn cleanup;\n\t\t\t}\n\t\t\tconst accumulated = text as string;\n\n\t\t\tif (!(\"calls\" in ctx.store)) {\n\t\t\t\tctx.store.calls = [] as ExtractedToolCall[];\n\t\t\t\tctx.store.scanFrom = 0;\n\t\t\t}\n\t\t\tconst calls = ctx.store.calls as ExtractedToolCall[];\n\t\t\tlet i = ctx.store.scanFrom as number;\n\t\t\tlet added = false;\n\n\t\t\twhile (i < accumulated.length) {\n\t\t\t\tconst start = accumulated.indexOf(\"{\", i);\n\t\t\t\tif (start === -1) {\n\t\t\t\t\tctx.store.scanFrom = accumulated.length;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tlet depth = 0;\n\t\t\t\tlet end = -1;\n\t\t\t\tlet inString = false;\n\t\t\t\tfor (let j = start; j < accumulated.length; j++) {\n\t\t\t\t\tconst ch = accumulated[j];\n\t\t\t\t\tif (inString) {\n\t\t\t\t\t\tif (ch === \"\\\\\" && j + 1 < accumulated.length) {\n\t\t\t\t\t\t\tj++; // skip escaped character\n\t\t\t\t\t\t} else if (ch === '\"') {\n\t\t\t\t\t\t\tinString = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (ch === '\"') {\n\t\t\t\t\t\tinString = true;\n\t\t\t\t\t} else if (ch === \"{\") {\n\t\t\t\t\t\tdepth++;\n\t\t\t\t\t} else if (ch === \"}\") {\n\t\t\t\t\t\tdepth--;\n\t\t\t\t\t\tif (depth === 0) {\n\t\t\t\t\t\t\tend = j;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (end === -1) {\n\t\t\t\t\t// Incomplete — resume brace-scanning from this open brace\n\t\t\t\t\t// next chunk. Do NOT advance past it.\n\t\t\t\t\tctx.store.scanFrom = start;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tconst raw = accumulated.slice(start, end + 1);\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(raw) as Record<string, unknown>;\n\t\t\t\t\tif (\n\t\t\t\t\t\ttypeof parsed.name === \"string\" &&\n\t\t\t\t\t\tparsed.arguments != null &&\n\t\t\t\t\t\ttypeof parsed.arguments === \"object\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tcalls.push({\n\t\t\t\t\t\t\tname: parsed.name,\n\t\t\t\t\t\t\targuments: parsed.arguments as Record<string, unknown>,\n\t\t\t\t\t\t\traw,\n\t\t\t\t\t\t\tstartIndex: start,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tadded = true;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Not valid JSON — skip\n\t\t\t\t}\n\t\t\t\ti = end + 1;\n\t\t\t\tctx.store.scanFrom = i;\n\t\t\t}\n\n\t\t\t// Always return a fresh copy so downstream never holds a live\n\t\t\t// reference to ctx.store.calls.\n\t\t\tactions.emit(added ? [...calls] : calls.slice());\n\t\t\treturn cleanup;\n\t\t},\n\t\t{\n\t\t\tname: opts?.name ?? \"tool-call-extractor\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tinitial: [],\n\t\t\tmeta: aiMeta(\"tool_call_extractor\"),\n\t\t\tequals: toolCallsEqual,\n\t\t},\n\t);\n}\n","/**\n * Content gate — classifies accumulated stream text as allow / review / block.\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\n\n/** Content safety decision. */\nexport type ContentDecision = \"allow\" | \"block\" | \"review\";\n\n/** Options for {@link contentGate}. */\nexport type ContentGateOptions = {\n\t/**\n\t * Hard-block threshold multiplier (default 1.5).\n\t * Scores above `threshold * hardMultiplier` emit `\"block\"`.\n\t * Scores between `threshold` and that emit `\"review\"`.\n\t */\n\thardMultiplier?: number;\n\tname?: string;\n};\n\n/**\n * Derived node that classifies accumulated stream text as `\"allow\"`,\n * `\"review\"`, or `\"block\"` based on a classifier score.\n *\n * **Wave A Unit 3 rewrite:** signature now takes `accumulatedText: Node<string>`\n * instead of a `TopicGraph<StreamChunk>` (the `StreamChunk` shape was retired\n * when the delta topic replaced the per-chunk accumulated-text shape).\n *\n * Emits a three-way decision on every text change:\n * - `\"allow\"` — score below `threshold`\n * - `\"review\"` — score in `[threshold, threshold × hardMultiplier)`\n * - `\"block\"` — score at or above `threshold × hardMultiplier`\n *\n * @param accumulatedText - Reactive accumulated-text source\n * (`streamingPromptNode(...).accumulatedText`).\n * @param classifier - `(accumulated: string) => number` scoring function, or\n * a `Node<number>` for live scores.\n * @param threshold - Score at which output becomes `\"review\"` or `\"block\"`.\n */\nexport function contentGate(\n\taccumulatedText: Node<string>,\n\tclassifier: ((accumulated: string) => number) | Node<number>,\n\tthreshold: number,\n\topts?: ContentGateOptions,\n): Node<ContentDecision> {\n\tconst hardThreshold = threshold * (opts?.hardMultiplier ?? 1.5);\n\tconst isNodeClassifier = typeof classifier !== \"function\";\n\n\tconst deps: Node<unknown>[] = [accumulatedText];\n\tif (isNodeClassifier) deps.push(classifier as Node<unknown>);\n\n\treturn node<ContentDecision>(\n\t\tdeps,\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 text = (data[0] as string | undefined) ?? \"\";\n\t\t\tif (text.length === 0) {\n\t\t\t\tactions.emit(\"allow\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst score = isNodeClassifier\n\t\t\t\t? ((data[1] as number | undefined) ?? 0)\n\t\t\t\t: (classifier as (t: string) => number)(text);\n\n\t\t\tif (score >= hardThreshold) {\n\t\t\t\tactions.emit(\"block\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (score >= threshold) {\n\t\t\t\tactions.emit(\"review\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tactions.emit(\"allow\");\n\t\t},\n\t\t{ describeKind: \"derived\", name: opts?.name ?? \"content-gate\", initial: \"allow\" },\n\t);\n}\n","/**\n * Redactor — stream extractor that replaces matched patterns in accumulated text.\n *\n * **Wave A Unit 3 rewrite:** signature now takes `accumulatedText: Node<string>`\n * instead of the retired `TopicGraph<StreamChunk>`. The output is a\n * `Node<string>` carrying the sanitized accumulated text — compose with\n * `contentGate` or downstream UI directly.\n *\n * @module\n */\n\nimport { type Node, node } from \"@graphrefly/pure-ts/core\";\n\n/** Options for {@link redactor}. */\nexport type RedactorOptions = {\n\tname?: string;\n};\n\n/**\n * Derived node that replaces matched patterns in accumulated text.\n *\n * @param accumulatedText - Reactive accumulated-text source.\n * @param patterns - Array of RegExps to match against the text.\n * @param replaceFn - Replacement producer (default: always `\"[REDACTED]\"`).\n * @returns `Node<string>` emitting the sanitized accumulated text.\n */\nexport function redactor(\n\taccumulatedText: Node<string>,\n\tpatterns: RegExp[],\n\treplaceFn?: (match: string, pattern: RegExp) => string,\n\topts?: RedactorOptions,\n): Node<string> {\n\tconst replace = replaceFn ?? (() => \"[REDACTED]\");\n\n\tfunction sanitize(text: string): string {\n\t\tlet result = text;\n\t\tfor (const pat of patterns) {\n\t\t\tconst global = pat.global ? pat : new RegExp(pat.source, `${pat.flags}g`);\n\t\t\tresult = result.replace(global, (m) => replace(m, pat));\n\t\t}\n\t\treturn result;\n\t}\n\n\treturn node<string>(\n\t\t[accumulatedText],\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\tactions.emit(sanitize((data[0] as string | undefined) ?? \"\"));\n\t\t},\n\t\t{ describeKind: \"derived\", name: opts?.name ?? \"redactor\", initial: \"\" },\n\t);\n}\n","import { factoryTag, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput, switchMap } from \"@graphrefly/pure-ts/extra\";\n\n// ---------------------------------------------------------------------------\n// handoff — multi-agent routing sugar (B10)\n// ---------------------------------------------------------------------------\n\n/**\n * Options for {@link handoff}.\n */\nexport type HandoffOptions = {\n\t/**\n\t * Reactive gate: when this node's value is `true`, output flows from\n\t * `from` to the `to` specialist; when `false`, `from`'s output flows\n\t * through unchanged and `to` stays dormant. Omit to always hand off —\n\t * useful when `from` is itself a router whose output shape already\n\t * encodes routing intent.\n\t */\n\tcondition?: NodeInput<boolean>;\n\tname?: string;\n};\n\n/**\n * Multi-agent handoff recipe — route `from`'s output into a specialist\n * agent `toFactory` when `condition` is open. Thin composition over\n * `switchMap` + gate; not a new primitive, just a named shape.\n *\n * The \"handoff\" pattern (popularized by the OpenAI Agents SDK) covers two\n * idioms:\n *\n * 1. **Full handoff** — a triage agent routes the conversation to a\n * specialist, and the specialist becomes the active agent for the rest\n * of the turn. Accumulated context (memory, tool definitions) can travel\n * along by threading the same `agentMemory` bundle into both.\n * 2. **Agents-as-tools** — the manager keeps control and calls the\n * specialist like a tool for a bounded subtask. Build this by registering\n * a `promptNode` instance as a `ToolDefinition` on the parent via\n * `toolRegistry`.\n *\n * This sugar covers (1) — a reactive route from one agent's output into a\n * specialist factory. For (2) wire a tool registry manually; the pattern is\n * additive with this one.\n *\n * @example Full handoff on a triage signal.\n * ```ts\n * import { handoff, promptNode } from \"@graphrefly/graphrefly/patterns/ai\";\n *\n * const triage = promptNode(adapter, [userMessage], (msg) =>\n * `Classify urgency of: ${msg}. Reply \"high\" or \"normal\".`);\n * const isUrgent = derived([triage], ([v]) => v === \"high\");\n *\n * const specialist = handoff(\n * userMessage,\n * (input) => promptNode(specialistAdapter, [input], (m) => `Respond urgently: ${m}`),\n * { condition: isUrgent },\n * );\n * ```\n *\n * @param from - Source node whose value is threaded into the specialist.\n * @param toFactory - Factory that takes `from` (as a reactive source) and\n * returns the specialist node. Called once, lazily, when the first\n * subscriber activates.\n * @param opts - Optional reactive `condition` gate + name.\n * @returns Node emitting the specialist's output when the gate is open, or\n * `from`'s value when the gate is closed. Null when `from` is null.\n *\n * **Performance caveat (Wave A Unit 5):** the specialist is mounted per\n * source emission — each `v != null` DATA on `from` allocates a fresh\n * `state<T>(v)` + invokes `toFactory`, and switchMap cancels the prior\n * branch. For per-turn routing (≤1 emit/sec) this is negligible. For\n * high-frequency sources (per-token routing, tight event loops), batch\n * upstream (e.g. via `audit`, `throttle`, or `distinctUntilChanged`) before\n * handing off — each mount/unmount cycle spins up full subgraphs\n * (`messagesNode` + adapter bridge + output for a `promptNode` specialist).\n *\n * @category patterns.ai\n */\nexport function handoff<T>(\n\tfrom: NodeInput<T | null>,\n\ttoFactory: (input: Node<T>) => Node<T | null>,\n\topts?: HandoffOptions,\n): Node<T | null> {\n\tconst src = fromAny(from);\n\tconst cond = opts?.condition != null ? fromAny(opts.condition) : null;\n\n\t// Shared `null` state — reused across null source emissions so repeated\n\t// nulls don't allocate a fresh node per switchMap project call.\n\tconst nullState: Node<T | null> = node<T | null>([], {\n\t\tinitial: null,\n\t\tname: opts?.name ? `${opts.name}::null` : \"handoff::null\",\n\t});\n\n\t// When no condition is supplied, always route through the specialist.\n\tif (cond == null) {\n\t\treturn switchMap<T | null, T | null>(\n\t\t\tsrc,\n\t\t\t(v) => {\n\t\t\t\tif (v == null) return nullState as NodeInput<T | null>;\n\t\t\t\tconst input = node<T>([], { initial: v });\n\t\t\t\treturn toFactory(input) as NodeInput<T | null>;\n\t\t\t},\n\t\t\t{ meta: factoryTag(\"handoff\") },\n\t\t);\n\t}\n\n\t// With a condition: pair src + cond into a router object, then switchMap\n\t// to either the specialist (when open) or a pass-through state (when\n\t// closed). Each router emission may re-instantiate the specialist — the\n\t// switchMap cancels the stale branch.\n\tconst router = node<{ v: T | null; open: boolean }>(\n\t\t[src, cond],\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\tactions.emit({ v: data[0] as T | null, open: data[1] === true });\n\t\t},\n\t\t{ name: opts?.name ? `${opts.name}::router` : \"handoff::router\", describeKind: \"derived\" },\n\t);\n\treturn switchMap<{ v: T | null; open: boolean }, T | null>(\n\t\trouter,\n\t\t({ v, open }) => {\n\t\t\tif (v == null) return nullState as NodeInput<T | null>;\n\t\t\tif (!open) return node<T | null>([], { initial: v }) as NodeInput<T | null>;\n\t\t\tconst input = node<T>([], { initial: v });\n\t\t\treturn toFactory(input) as NodeInput<T | null>;\n\t\t},\n\t\t{ meta: factoryTag(\"handoff\") },\n\t);\n}\n","import { factoryTag, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput } from \"@graphrefly/pure-ts/extra\";\nimport { aiMeta } from \"../_internal.js\";\nimport type { ToolDefinition } from \"../adapters/core/types.js\";\n\n// ---------------------------------------------------------------------------\n// toolSelector — reactive tool availability (D8 / COMPOSITION-GUIDE §31)\n// ---------------------------------------------------------------------------\n\n/**\n * Options for {@link toolSelector}.\n */\nexport interface ToolSelectorOptions {\n\treadonly name?: string;\n}\n\n/**\n * Reactive tool availability (COMPOSITION-GUIDE §31). Given a base tool set\n * (reactive or static) and one or more reactive predicates, emit the filtered\n * subset of tools currently allowed. Feeds into `promptNode({ tools: Node<...> })`\n * so the LLM sees a reactive menu instead of a frozen config.\n *\n * Each predicate is a `NodeInput<(tool) => boolean>`. A tool is included iff\n * **every** predicate returns `true`. When any predicate value is `null` /\n * `undefined` (e.g. upstream not yet ready) that predicate is treated as a\n * pass-through — the tool isn't excluded on its basis. Predicate updates\n * recompute the selected set.\n *\n * Pairs with `toolInterceptor` (§D9 / §31): **selection** controls what's\n * offered to the LLM (pre-generation UX); **interception** gates what's\n * executed after the LLM chooses (post-generation security). Tool selection\n * is NOT a security boundary — an LLM can hallucinate tool calls outside\n * its offered set; always pair with `toolInterceptor` for enforcement.\n *\n * @example\n * ```ts\n * const hasBudget = node([costMeter], (batchData, actions, ctx) => {\n * const data = batchData.map((batch, i) => batch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i]);\n * actions.emit((data[0] as CostMeter).total < BUDGET);\n * }, { describeKind: \"derived\" });\n * const canDestroy = state(false, { name: \"destructive-allowed\" });\n * const tools = toolSelector(registry.schemas, [\n * node([hasBudget], (batchData, actions, ctx) => {\n * const data = batchData.map((batch, i) => batch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i]);\n * actions.emit((t) => !t.meta?.expensive || data[0] === true);\n * }, { describeKind: \"derived\" }),\n * node([canDestroy], (batchData, actions, ctx) => {\n * const data = batchData.map((batch, i) => batch != null && batch.length > 0 ? batch.at(-1) : ctx.prevData[i]);\n * actions.emit((t) => !t.meta?.destructive || data[0] === true);\n * }, { describeKind: \"derived\" }),\n * ]);\n * const agent = promptNode(graph, \"agent\", { ..., tools });\n * ```\n */\nexport function toolSelector(\n\tallTools: NodeInput<readonly ToolDefinition[]>,\n\tconstraints: readonly NodeInput<(tool: ToolDefinition) => boolean>[],\n\topts?: ToolSelectorOptions,\n): Node<readonly ToolDefinition[]> {\n\tconst allToolsNode = fromAny(allTools);\n\tconst constraintNodes = constraints.map((c) => fromAny(c));\n\tconst deps = [allToolsNode, ...constraintNodes] as const;\n\treturn node<readonly ToolDefinition[]>(\n\t\tdeps,\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 tools = (data[0] as readonly ToolDefinition[] | null | undefined) ?? [];\n\t\t\tconst preds = data.slice(1) as ReadonlyArray<\n\t\t\t\t((t: ToolDefinition) => boolean) | null | undefined\n\t\t\t>;\n\t\t\tactions.emit(\n\t\t\t\ttools.filter((tool) => {\n\t\t\t\t\tfor (const pred of preds) {\n\t\t\t\t\t\t// Pass-through when a predicate hasn't settled — callers with\n\t\t\t\t\t\t// async constraints should not have every tool silently dropped\n\t\t\t\t\t\t// on the first emit. Constraints are \"deny when false\", not\n\t\t\t\t\t\t// \"deny when not yet ready\".\n\t\t\t\t\t\tif (pred == null) continue;\n\t\t\t\t\t\tif (!pred(tool)) return false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t\t{\n\t\t\tname: opts?.name ?? \"tool-selector\",\n\t\t\tdescribeKind: \"derived\",\n\t\t\tmeta: { ...aiMeta(\"tool_selector\"), ...factoryTag(\"toolSelector\") },\n\t\t\tequals: (a, b) => {\n\t\t\t\tconst la = a as readonly ToolDefinition[];\n\t\t\t\tconst lb = b as readonly ToolDefinition[];\n\t\t\t\tif (la.length !== lb.length) return false;\n\t\t\t\tfor (let i = 0; i < la.length; i++) {\n\t\t\t\t\tif (la[i] !== lb[i]) return false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t},\n\t\t},\n\t);\n}\n","// ---------------------------------------------------------------------------\n// Admission scoring (generic + 3D sugar)\n// ---------------------------------------------------------------------------\n//\n// `admissionScored<Dims>` is the generic primitive: a user-supplied scoreFn\n// returns one number per named dimension; the filter rejects whenever any\n// scored dimension falls below its configured threshold. Dimensions absent\n// from the thresholds config are ignored — they may still be useful for\n// telemetry, but don't gate admission.\n//\n// `admissionFilter3D` is a thin wrapper for the persistence / structure /\n// personalValue triple borrowed from the LLM memory literature; ship this\n// when callers want the named-axes shape, otherwise compose `admissionScored`\n// directly with whatever dimensions fit the domain.\n//\n// The earlier `defaultAdmissionScorer` (always-0.5 across all dims) was\n// retired in Unit 8 — it admitted everything in disguise. Callers must\n// supply a real `scoreFn`.\n\n/** Generic per-dimension thresholds. Any dim below its threshold → reject. */\nexport type AdmissionThresholds<Dims extends string> = Partial<Record<Dims, number>>;\n\nexport type AdmissionScoredOptions<Dims extends string, TRaw = unknown> = {\n\t/** Score function — must return a finite number for every dimension named in `thresholds`. */\n\tscoreFn: (raw: TRaw) => Readonly<Record<Dims, number>>;\n\t/** Per-dim minimums. Dims absent here are scored but not gated. */\n\tthresholds?: AdmissionThresholds<Dims>;\n};\n\n/**\n * Generic N-dimension admission filter. Rejects any input where one of the\n * configured threshold dimensions scores below its minimum. Missing scores\n * (`undefined` / `null`) AND non-finite values (`NaN`, `±Infinity`) are\n * treated as below all thresholds — reject by default rather than admit.\n *\n * @example\n * ```ts\n * const filter = admissionScored({\n * scoreFn: (raw: Note) => ({ relevance: scoreRelevance(raw), age: ageScore(raw) }),\n * thresholds: { relevance: 0.4 }, // age scored but ungated\n * });\n * ```\n */\nexport function admissionScored<Dims extends string, TRaw = unknown>(\n\topts: AdmissionScoredOptions<Dims, TRaw>,\n): (raw: TRaw) => boolean {\n\tconst thresholds = opts.thresholds ?? ({} as AdmissionThresholds<Dims>);\n\treturn (raw: TRaw): boolean => {\n\t\tconst scores = opts.scoreFn(raw);\n\t\tfor (const dim of Object.keys(thresholds) as Dims[]) {\n\t\t\tconst min = thresholds[dim];\n\t\t\tif (min === undefined) continue;\n\t\t\tconst s = scores[dim];\n\t\t\t// `??` falls back on null/undefined but lets NaN through; we want\n\t\t\t// non-finite to also reject so a buggy scoreFn returning NaN doesn't\n\t\t\t// silently admit. `Number.isFinite(NaN) === false`.\n\t\t\tconst safe = Number.isFinite(s) ? (s as number) : Number.NEGATIVE_INFINITY;\n\t\t\tif (safe < min) return false;\n\t\t}\n\t\treturn true;\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// 3D sugar\n// ---------------------------------------------------------------------------\n\n/** Scores for the three admission dimensions. Each 0–1. */\nexport type AdmissionScores = {\n\treadonly persistence: number;\n\treadonly structure: number;\n\treadonly personalValue: number;\n};\n\nexport type AdmissionScore3DOptions = {\n\t/** Custom scoring function. Required — the previous always-0.5 default was misleading. */\n\tscoreFn: (raw: unknown) => AdmissionScores;\n\t/** Minimum persistence score to admit (default 0.3). */\n\tpersistenceThreshold?: number;\n\t/** Minimum personalValue score to admit (default 0.3). */\n\tpersonalValueThreshold?: number;\n\t/** Require structure score > 0 to admit (default false). */\n\trequireStructured?: boolean;\n};\n\n/**\n * 3D admission sugar — the persistence / structure / personalValue triple\n * commonly used in agent-memory literature. Composes `admissionScored`\n * with thresholds derived from the option fields. Use directly when those\n * three named dimensions match your domain, or use `admissionScored` with\n * an arbitrary dimension set instead.\n *\n * `requireStructured: true` rejects entries where `structure <= 0` (matches\n * the pre-Unit-8 `requireStructured && scores.structure <= 0` check).\n * Implemented as a final-step predicate around `admissionScored` rather\n * than a `Number.MIN_VALUE` threshold, which would have been a footgun for\n * future readers.\n */\nexport function admissionFilter3D(opts: AdmissionScore3DOptions): (raw: unknown) => boolean {\n\tconst thresholds: AdmissionThresholds<keyof AdmissionScores> = {\n\t\tpersistence: opts.persistenceThreshold ?? 0.3,\n\t\tpersonalValue: opts.personalValueThreshold ?? 0.3,\n\t};\n\tconst base = admissionScored<keyof AdmissionScores, unknown>({\n\t\tscoreFn: opts.scoreFn,\n\t\tthresholds,\n\t});\n\tif (!opts.requireStructured) return base;\n\treturn (raw: unknown): boolean => {\n\t\tif (!base(raw)) return false;\n\t\tconst s = opts.scoreFn(raw).structure;\n\t\treturn Number.isFinite(s) && s > 0;\n\t};\n}\n","// ---------------------------------------------------------------------------\n// gaugesAsContext\n// ---------------------------------------------------------------------------\n\nimport type { Actor } from \"@graphrefly/pure-ts/core\";\nimport type { Graph } from \"@graphrefly/pure-ts/graph\";\n\nexport type GaugesAsContextOptions = {\n\t/** Group gauges by `meta.tags` (default true). */\n\tgroupByTags?: boolean;\n\t/** Separator between gauge lines (default \"\\n\"). */\n\tseparator?: string;\n\t/**\n\t * V0 delta mode (§6.0b): only include nodes whose `v.version` exceeds\n\t * the corresponding entry in this map. Nodes without V0 or not in the\n\t * map are always included. Callers maintain this map across calls.\n\t *\n\t * The `id` field guards against node replacement: if a node is removed\n\t * and re-added under the same name (new id), it is always included.\n\t */\n\tsinceVersion?: ReadonlyMap<string, { id: string; version: number }>;\n};\n\n/**\n * Format a graph's readable (gauge) nodes as a context string for LLM\n * system prompts.\n *\n * Gauges are nodes with `meta.description` or `meta.format`. Values are\n * formatted using `meta.format` and `meta.unit` hints.\n *\n * @param graph - The graph to introspect.\n * @param actor - Optional actor for guard-scoped describe.\n * @param options - Formatting options.\n * @returns A formatted string ready for system prompt injection.\n */\nexport function gaugesAsContext(\n\tgraph: Graph,\n\tactor?: Actor,\n\toptions?: GaugesAsContextOptions,\n): string {\n\tconst described = graph.describe({ actor, detail: \"full\" });\n\tconst groupByTags = options?.groupByTags ?? true;\n\tconst separator = options?.separator ?? \"\\n\";\n\n\ttype GaugeEntry = { path: string; description: string; formatted: string };\n\tconst entries: GaugeEntry[] = [];\n\n\tconst sinceVersion = options?.sinceVersion;\n\tfor (const [path, node] of Object.entries(described.nodes)) {\n\t\tconst meta = node.meta ?? {};\n\t\tconst desc = meta.description as string | undefined;\n\t\tconst format = meta.format as string | undefined;\n\t\t// Must have description or format to be a gauge\n\t\tif (!desc && !format) continue;\n\t\t// V0 delta filter: skip nodes unchanged since last seen version (§6.0b).\n\t\tif (sinceVersion != null && node.v != null) {\n\t\t\tconst lastSeen = sinceVersion.get(path);\n\t\t\tif (lastSeen != null && lastSeen.id === node.v.id && node.v.version <= lastSeen.version)\n\t\t\t\tcontinue;\n\t\t}\n\n\t\tconst label = desc ?? path;\n\t\tconst value = node.value;\n\t\tconst unit = meta.unit as string | undefined;\n\n\t\tlet formatted: string;\n\t\tif (format === \"currency\" && typeof value === \"number\") {\n\t\t\tformatted = `$${value.toFixed(2)}`;\n\t\t} else if (format === \"percentage\" && typeof value === \"number\") {\n\t\t\tformatted = `${(value * 100).toFixed(1)}%`;\n\t\t} else if (value === undefined || value === null) {\n\t\t\tformatted = \"(no value)\";\n\t\t} else {\n\t\t\tformatted = String(value);\n\t\t}\n\n\t\tif (unit && format !== \"currency\" && format !== \"percentage\") {\n\t\t\tformatted = `${formatted} ${unit}`;\n\t\t}\n\n\t\tentries.push({ path, description: label, formatted });\n\t}\n\n\tif (entries.length === 0) return \"\";\n\n\tif (groupByTags) {\n\t\tconst tagGroups = new Map<string, GaugeEntry[]>();\n\t\tconst ungrouped: GaugeEntry[] = [];\n\n\t\tfor (const entry of entries) {\n\t\t\tconst node = described.nodes[entry.path]!;\n\t\t\tconst tags = node.meta?.tags as string[] | undefined;\n\t\t\tif (tags && tags.length > 0) {\n\t\t\t\t// Use first tag for grouping to avoid duplicating entries across groups\n\t\t\t\tconst tag = tags[0]!;\n\t\t\t\tlet group = tagGroups.get(tag);\n\t\t\t\tif (!group) {\n\t\t\t\t\tgroup = [];\n\t\t\t\t\ttagGroups.set(tag, group);\n\t\t\t\t}\n\t\t\t\tgroup.push(entry);\n\t\t\t} else {\n\t\t\t\tungrouped.push(entry);\n\t\t\t}\n\t\t}\n\n\t\tif (tagGroups.size === 0) {\n\t\t\treturn entries.map((e) => `- ${e.description}: ${e.formatted}`).join(separator);\n\t\t}\n\n\t\tconst sections: string[] = [];\n\t\tfor (const [tag, group] of [...tagGroups.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {\n\t\t\tsections.push(\n\t\t\t\t`[${tag}]${separator}${group.map((e) => `- ${e.description}: ${e.formatted}`).join(separator)}`,\n\t\t\t);\n\t\t}\n\t\tif (ungrouped.length > 0) {\n\t\t\tsections.push(ungrouped.map((e) => `- ${e.description}: ${e.formatted}`).join(separator));\n\t\t}\n\t\treturn sections.join(separator + separator);\n\t}\n\n\treturn entries.map((e) => `- ${e.description}: ${e.formatted}`).join(separator);\n}\n","// ---------------------------------------------------------------------------\n// graphFromSpec\n// ---------------------------------------------------------------------------\n\nimport { COMPLETE, ERROR, type Node, node } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput, switchMap } from \"@graphrefly/pure-ts/extra\";\nimport type { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { compileSpec, type GraphSpec, type GraphSpecCatalog } from \"../../graphspec/index.js\";\nimport { resolveToolHandlerResult, stripFences } from \"../_internal.js\";\nimport type { ChatMessage, LLMAdapter, LLMResponse } from \"../adapters/core/types.js\";\n\nexport type GraphFromSpecOptions = {\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\t/** Fn/source catalog for resolving named node factories from the LLM-generated spec. */\n\tcatalog?: GraphSpecCatalog;\n\t/** Extra instructions appended to the system prompt. */\n\tsystemPromptExtra?: string;\n\t/**\n\t * Optional AbortSignal forwarded to `adapter.invoke({ signal })`. Lets\n\t * callers cancel the in-flight LLM call (e.g. when the reactive variant\n\t * supersedes mid-flight). When the signal aborts, the underlying call\n\t * propagates the abort and `graphFromSpec` rejects with the abort reason.\n\t */\n\tsignal?: AbortSignal;\n};\n\nconst GRAPH_FROM_SPEC_SYSTEM_PROMPT = `You are a graph architect for GraphReFly, a reactive graph protocol.\n\nGiven a natural-language description, produce a JSON graph specification with this structure:\n\n{\n \"name\": \"<graph_name>\",\n \"nodes\": {\n \"<node_name>\": {\n \"type\": \"state\" | \"derived\" | \"producer\" | \"effect\" | \"operator\",\n \"initial\": <initial_value_for_state_nodes>,\n \"deps\": [\"<dep_node_name>\", ...],\n \"meta\": {\n \"description\": \"<human-readable purpose>\",\n \"type\": \"string\" | \"number\" | \"boolean\" | \"integer\" | \"enum\",\n \"range\": [min, max],\n \"values\": [\"a\", \"b\"],\n \"format\": \"currency\" | \"percentage\" | \"status\",\n \"access\": \"human\" | \"llm\" | \"both\" | \"system\",\n \"unit\": \"<unit>\",\n \"tags\": [\"<tag>\"]\n }\n }\n }\n}\n\nRules:\n- \"state\" nodes have no deps and hold user/LLM-writable values (knobs). Use \"initial\" for the starting value.\n- \"derived\" nodes have deps and compute from them (pure, no side effects).\n- \"effect\" nodes have deps but produce side effects (no return value).\n- \"producer\" nodes have no deps but generate values asynchronously.\n- \"operator\" nodes are parameterized transformations with deps.\n- Use \"deps\" inside each node to declare dependencies — no separate \"edges\" array.\n- meta.description is required for every node.\n- Return ONLY valid JSON, no markdown fences or commentary.`;\n\n/**\n * Ask an LLM to compose a Graph from a natural-language description.\n *\n * The LLM returns a JSON {@link GraphSpec} which is validated, catalog-expanded,\n * and instantiated via {@link compileSpec} (gains catalog validation, template\n * expansion, and feedback wiring that `Graph.fromSnapshot` bypasses).\n *\n * @param naturalLanguage - The problem/use-case description.\n * @param adapter - LLM adapter for the generation call.\n * @param opts - Model options and optional catalog for named node factories.\n * @returns A constructed Graph.\n * @throws On invalid LLM output, validation failure, or unresolvable deps.\n */\nexport async function graphFromSpec(\n\tnaturalLanguage: string,\n\tadapter: LLMAdapter,\n\topts?: GraphFromSpecOptions,\n): Promise<Graph> {\n\tconst systemPrompt = opts?.systemPromptExtra\n\t\t? `${GRAPH_FROM_SPEC_SYSTEM_PROMPT}\\n\\n${opts.systemPromptExtra}`\n\t\t: GRAPH_FROM_SPEC_SYSTEM_PROMPT;\n\n\tconst messages: ChatMessage[] = [\n\t\t{ role: \"system\", content: systemPrompt },\n\t\t{ role: \"user\", content: naturalLanguage },\n\t];\n\n\tconst rawResult = adapter.invoke(messages, {\n\t\tmodel: opts?.model,\n\t\ttemperature: opts?.temperature ?? 0,\n\t\tmaxTokens: opts?.maxTokens,\n\t\tsignal: opts?.signal,\n\t});\n\n\tconst response = (await resolveToolHandlerResult(rawResult)) as LLMResponse;\n\tlet content = response.content.trim();\n\n\t// Strip markdown fences if present (handles trailing commentary after ```)\n\tif (content.startsWith(\"```\")) {\n\t\tcontent = stripFences(content);\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(content);\n\t} catch {\n\t\tthrow new Error(`graphFromSpec: LLM response is not valid JSON: ${content.slice(0, 200)}`);\n\t}\n\n\treturn compileSpec(parsed as GraphSpec, { catalog: opts?.catalog });\n}\n\n/**\n * Reactive variant of {@link graphFromSpec}: re-invokes the LLM and\n * recompiles the graph whenever `input` emits a new natural-language\n * description. Useful inside the harness or refine loop when the spec text\n * itself is a reactive value (e.g. fed by a `node([], { initial: ... })` knob, a memory\n * snapshot, or an upstream `promptNode` output).\n *\n * **Supersede:** when the input changes mid-flight, switchMap tears the\n * inner producer down. The producer's cleanup aborts the in-flight LLM\n * call via an internal `AbortController` (threaded into `graphFromSpec`'s\n * new `signal` option) AND destroys any Graph that lands after cancel —\n * no token leak, no unreferenced compiled graphs. If the user's input\n * already changed by the time the LLM responds, the about-to-be-discarded\n * Graph is freed instead of orphaned.\n *\n * **Lifetime of the latest emitted Graph:** the caller owns each Graph\n * that actually reaches them. If you keep multiple historical values, call\n * `prev?.destroy()` before storing the new one.\n *\n * @param input - Reactive source of natural-language descriptions.\n * @param adapter - LLM adapter for the generation call.\n * @param opts - Model options and optional catalog for named node factories.\n * @returns `Node<Graph | null>` — emits the latest compiled graph, or `null`\n * while the input is empty / unsettled.\n */\nexport function graphFromSpecReactive(\n\tinput: NodeInput<string>,\n\tadapter: LLMAdapter,\n\topts?: GraphFromSpecOptions,\n): Node<Graph | null> {\n\tconst inputNode = fromAny(input);\n\treturn switchMap<string, Graph | null>(inputNode, (nl) => {\n\t\tif (!nl || typeof nl !== \"string\" || nl.trim().length === 0) {\n\t\t\treturn node<Graph | null>([], { initial: null });\n\t\t}\n\t\t// Producer guarantees a single DATA + COMPLETE per upstream wave —\n\t\t// matches the `promptNode` shape (see Unit 1 review). On supersede,\n\t\t// switchMap tears down the producer; cleanup aborts the in-flight LLM\n\t\t// call AND destroys any Graph that lands post-abort (would otherwise\n\t\t// leak its mounted state nodes / storage handles until GC).\n\t\treturn node<Graph | null>(\n\t\t\t(_data, actions) => {\n\t\t\t\tconst controller = new AbortController();\n\t\t\t\tlet cancelled = false;\n\t\t\t\tgraphFromSpec(nl, adapter, { ...opts, signal: controller.signal })\n\t\t\t\t\t.then((g) => {\n\t\t\t\t\t\tif (cancelled) {\n\t\t\t\t\t\t\tg.destroy();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tactions.emit(g);\n\t\t\t\t\t\tactions.down([[COMPLETE]]);\n\t\t\t\t\t})\n\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\tif (cancelled) return;\n\t\t\t\t\t\tactions.down([[ERROR, err]]);\n\t\t\t\t\t});\n\t\t\t\treturn () => {\n\t\t\t\t\tcancelled = true;\n\t\t\t\t\tcontroller.abort();\n\t\t\t\t};\n\t\t\t},\n\t\t\t{ describeKind: \"producer\", ...{ name: \"graphFromSpec::call\" } },\n\t\t);\n\t});\n}\n","// ---------------------------------------------------------------------------\n// 5.4 — LLM tool integration\n// ---------------------------------------------------------------------------\n\nimport type { Actor } from \"@graphrefly/pure-ts/core\";\nimport type { Graph } from \"@graphrefly/pure-ts/graph\";\nimport type { ToolDefinition } from \"../adapters/core/types.js\";\n\n/** OpenAI function-calling tool schema. */\nexport type OpenAIToolSchema = {\n\treadonly type: \"function\";\n\treadonly function: {\n\t\treadonly name: string;\n\t\treadonly description: string;\n\t\treadonly parameters: Record<string, unknown>;\n\t};\n};\n\n/** MCP (Model Context Protocol) tool schema. */\nexport type McpToolSchema = {\n\treadonly name: string;\n\treadonly description: string;\n\treadonly inputSchema: Record<string, unknown>;\n};\n\n/** Result of {@link knobsAsTools}. */\nexport type KnobsAsToolsResult = {\n\t/** OpenAI function-calling tool schemas. */\n\treadonly openai: readonly OpenAIToolSchema[];\n\t/** MCP tool schemas. */\n\treadonly mcp: readonly McpToolSchema[];\n\t/** GraphReFly ToolDefinitions with handlers that call `graph.set()`. */\n\treadonly definitions: readonly ToolDefinition[];\n};\n\n/**\n * Build a JSON Schema `properties.value` descriptor from a node's meta fields.\n *\n * Maps `meta.type`, `meta.range`, `meta.values`, `meta.format`, and `meta.unit`\n * to a JSON Schema property definition.\n */\nfunction metaToJsonSchema(meta: Record<string, unknown>): Record<string, unknown> {\n\tconst schema: Record<string, unknown> = {};\n\n\tconst metaType = meta.type as string | undefined;\n\tif (metaType === \"enum\" && Array.isArray(meta.values)) {\n\t\tschema.type = \"string\";\n\t\tschema.enum = meta.values;\n\t} else if (metaType === \"integer\") {\n\t\tschema.type = \"integer\";\n\t} else if (metaType === \"number\") {\n\t\tschema.type = \"number\";\n\t} else if (metaType === \"boolean\") {\n\t\tschema.type = \"boolean\";\n\t} else if (metaType === \"string\") {\n\t\tschema.type = \"string\";\n\t} else {\n\t\t// Unknown or unspecified — accept anything\n\t\tschema.type = [\"string\", \"number\", \"boolean\"];\n\t}\n\n\tif (Array.isArray(meta.range) && meta.range.length === 2) {\n\t\tschema.minimum = meta.range[0];\n\t\tschema.maximum = meta.range[1];\n\t}\n\n\tif (typeof meta.format === \"string\") {\n\t\tschema.description = `Format: ${meta.format}`;\n\t}\n\n\tif (typeof meta.unit === \"string\") {\n\t\tif (schema.description) {\n\t\t\tschema.description += ` (${meta.unit})`;\n\t\t} else {\n\t\t\tschema.description = `Unit: ${meta.unit}`;\n\t\t}\n\t}\n\n\treturn schema;\n}\n\n/**\n * Derive tool schemas from a graph's writable (knob) nodes.\n *\n * Knobs are state nodes whose `meta.access` is `\"llm\"`, `\"both\"`, or absent\n * (default: writable). Each knob becomes a tool that calls `graph.set()`.\n *\n * Speaks **domain language** (spec §5.4): the returned schemas use node names\n * and meta descriptions — no protocol internals exposed.\n *\n * @param graph - The graph to introspect.\n * @param actor - Optional actor for guard-scoped describe.\n * @returns OpenAI, MCP, and GraphReFly tool schemas.\n */\nexport function knobsAsTools(graph: Graph, actor?: Actor): KnobsAsToolsResult {\n\tconst described = graph.describe({ actor, detail: \"full\" });\n\tconst openai: OpenAIToolSchema[] = [];\n\tconst mcp: McpToolSchema[] = [];\n\tconst definitions: ToolDefinition[] = [];\n\n\tfor (const [path, node] of Object.entries(described.nodes)) {\n\t\t// Only state nodes are writable knobs\n\t\tif (node.type !== \"state\") continue;\n\n\t\t// Skip meta companion nodes (§2.3)\n\t\tif (path.includes(\"::__meta__::\")) continue;\n\n\t\t// Skip terminal-state nodes (§1.3.4 — no further messages after COMPLETE/ERROR)\n\t\tif (node.status === \"completed\" || node.status === \"errored\") continue;\n\n\t\t// Skip if access explicitly excludes LLM\n\t\tconst meta = node.meta ?? {};\n\t\tconst access = meta.access as string | undefined;\n\t\tif (access === \"human\" || access === \"system\") continue;\n\n\t\tconst description = (meta.description as string) ?? `Set the value of ${path}`;\n\t\tconst valueSchema = metaToJsonSchema(meta);\n\n\t\tconst parameterSchema: Record<string, unknown> = {\n\t\t\ttype: \"object\",\n\t\t\trequired: [\"value\"],\n\t\t\tproperties: {\n\t\t\t\tvalue: valueSchema,\n\t\t\t},\n\t\t\tadditionalProperties: false,\n\t\t};\n\n\t\t// OpenAI requires [a-zA-Z0-9_-] in function names; sanitize :: separators\n\t\tconst sanitizedName = path.replace(/::/g, \"__\");\n\n\t\topenai.push({\n\t\t\ttype: \"function\",\n\t\t\tfunction: {\n\t\t\t\tname: sanitizedName,\n\t\t\t\tdescription,\n\t\t\t\tparameters: parameterSchema,\n\t\t\t},\n\t\t});\n\n\t\tmcp.push({\n\t\t\tname: path,\n\t\t\tdescription,\n\t\t\tinputSchema: parameterSchema,\n\t\t});\n\n\t\tconst graphRef = graph;\n\t\tconst actorRef = actor;\n\t\tconst nv = node.v;\n\t\tdefinitions.push({\n\t\t\tname: path,\n\t\t\tdescription,\n\t\t\tparameters: parameterSchema,\n\t\t\thandler(args: Record<string, unknown>) {\n\t\t\t\tgraphRef.set(path, args.value, actorRef ? { actor: actorRef } : undefined);\n\t\t\t\treturn args.value;\n\t\t\t},\n\t\t\t...(nv != null ? { version: { id: nv.id, version: nv.version } } : {}),\n\t\t});\n\t}\n\n\treturn { openai, mcp, definitions };\n}\n","// ---------------------------------------------------------------------------\n// suggestStrategy\n// ---------------------------------------------------------------------------\n\nimport type { Actor, Node } from \"@graphrefly/pure-ts/core\";\nimport { COMPLETE, ERROR, node } from \"@graphrefly/pure-ts/core\";\nimport { fromAny, type NodeInput, switchMap, withLatestFrom } from \"@graphrefly/pure-ts/extra\";\nimport type { Graph } from \"@graphrefly/pure-ts/graph\";\nimport { resolveToolHandlerResult } from \"../_internal.js\";\nimport type { ChatMessage, LLMAdapter, LLMResponse } from \"../adapters/core/types.js\";\n\n/** A single operation in a strategy plan. */\nexport type StrategyOperation =\n\t| {\n\t\t\treadonly type: \"add_node\";\n\t\t\treadonly name: string;\n\t\t\treadonly nodeType: string;\n\t\t\treadonly meta?: Record<string, unknown>;\n\t\t\treadonly initial?: unknown;\n\t }\n\t| { readonly type: \"remove_node\"; readonly name: string }\n\t| { readonly type: \"connect\"; readonly from: string; readonly to: string }\n\t| { readonly type: \"disconnect\"; readonly from: string; readonly to: string }\n\t| { readonly type: \"set_value\"; readonly name: string; readonly value: unknown }\n\t| {\n\t\t\treadonly type: \"update_meta\";\n\t\t\treadonly name: string;\n\t\t\treadonly key: string;\n\t\t\treadonly value: unknown;\n\t };\n\n/** Structured strategy plan returned by {@link suggestStrategy}. */\nexport type StrategyPlan = {\n\treadonly summary: string;\n\treadonly operations: readonly StrategyOperation[];\n\treadonly reasoning: string;\n};\n\nexport type SuggestStrategyOptions = {\n\tmodel?: string;\n\ttemperature?: number;\n\tmaxTokens?: number;\n\tactor?: Actor;\n\t/**\n\t * Optional AbortSignal forwarded to `adapter.invoke({ signal })`. Lets\n\t * callers cancel the in-flight LLM call (e.g. when the reactive variant\n\t * supersedes mid-flight). When the signal aborts, the underlying call\n\t * propagates the abort and `suggestStrategy` rejects with the abort reason.\n\t */\n\tsignal?: AbortSignal;\n};\n\nconst SUGGEST_STRATEGY_SYSTEM_PROMPT = `You are a reactive graph optimizer for GraphReFly.\n\nGiven a graph's current structure (from describe()) and a problem statement, suggest topology and parameter changes to solve the problem.\n\nReturn ONLY valid JSON with this structure:\n{\n \"summary\": \"<one-line summary of the strategy>\",\n \"reasoning\": \"<explanation of why these changes help>\",\n \"operations\": [\n { \"type\": \"add_node\", \"name\": \"<name>\", \"nodeType\": \"state|derived|effect|producer|operator\", \"meta\": {...}, \"initial\": <value> },\n { \"type\": \"remove_node\", \"name\": \"<name>\" },\n { \"type\": \"connect\", \"from\": \"<source>\", \"to\": \"<target>\" },\n { \"type\": \"disconnect\", \"from\": \"<source>\", \"to\": \"<target>\" },\n { \"type\": \"set_value\", \"name\": \"<name>\", \"value\": <new_value> },\n { \"type\": \"update_meta\", \"name\": \"<name>\", \"key\": \"<meta_key>\", \"value\": <new_value> }\n ]\n}\n\nRules:\n- Only suggest operations that reference existing nodes (for remove/disconnect/set_value/update_meta) or new nodes you define (for add_node).\n- Keep changes minimal — prefer the smallest set of operations that solves the problem.\n- Return ONLY valid JSON, no markdown fences or commentary.`;\n\n/**\n * Ask an LLM to analyze a graph and suggest topology/parameter changes\n * to solve a stated problem.\n *\n * Returns a structured plan — does NOT auto-apply. The caller reviews\n * and selectively applies operations.\n *\n * @param graph - The graph to analyze.\n * @param problem - Natural-language problem statement.\n * @param adapter - LLM adapter for the analysis call.\n * @param opts - Model and actor options.\n * @returns A structured strategy plan.\n * @throws On invalid LLM output.\n */\nexport async function suggestStrategy(\n\tgraph: Graph,\n\tproblem: string,\n\tadapter: LLMAdapter,\n\topts?: SuggestStrategyOptions,\n): Promise<StrategyPlan> {\n\tconst { expand: _, ...described } = graph.describe({ actor: opts?.actor, detail: \"standard\" });\n\n\tconst messages: ChatMessage[] = [\n\t\t{ role: \"system\", content: SUGGEST_STRATEGY_SYSTEM_PROMPT },\n\t\t{\n\t\t\trole: \"user\",\n\t\t\tcontent: JSON.stringify({\n\t\t\t\tgraph: described,\n\t\t\t\tproblem,\n\t\t\t}),\n\t\t},\n\t];\n\n\tconst rawResult = adapter.invoke(messages, {\n\t\tmodel: opts?.model,\n\t\ttemperature: opts?.temperature ?? 0,\n\t\tmaxTokens: opts?.maxTokens,\n\t\tsignal: opts?.signal,\n\t});\n\n\tconst response = (await resolveToolHandlerResult(rawResult)) as LLMResponse;\n\tlet content = response.content.trim();\n\n\tif (content.startsWith(\"```\")) {\n\t\tcontent = content.replace(/^```(?:json)?\\s*/, \"\").replace(/\\s*```$/, \"\");\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(content);\n\t} catch {\n\t\tthrow new Error(`suggestStrategy: LLM response is not valid JSON: ${content.slice(0, 200)}`);\n\t}\n\n\tconst plan = parsed as Record<string, unknown>;\n\n\tif (typeof plan.summary !== \"string\") {\n\t\tthrow new Error(\"suggestStrategy: missing 'summary' in response\");\n\t}\n\tif (typeof plan.reasoning !== \"string\") {\n\t\tthrow new Error(\"suggestStrategy: missing 'reasoning' in response\");\n\t}\n\tif (!Array.isArray(plan.operations)) {\n\t\tthrow new Error(\"suggestStrategy: missing 'operations' array in response\");\n\t}\n\n\treturn {\n\t\tsummary: plan.summary,\n\t\treasoning: plan.reasoning,\n\t\toperations: plan.operations as readonly StrategyOperation[],\n\t};\n}\n\n/**\n * Reactive variant of {@link suggestStrategy}: re-invokes the LLM whenever\n * the `problem` source emits, sampling the latest `graph` value (via\n * `withLatestFrom`) to describe. The graph is the *secondary* dep — only\n * problem changes re-trigger analysis. This breaks the feedback cycle that\n * would otherwise arise if downstream consumers wired `apply(plan)` back\n * into the same graph node (graph mutation must not auto-fire a re-analysis).\n *\n * @param graph - Reactive source of graphs to analyze.\n * @param problem - Reactive source of natural-language problem statements.\n * @param adapter - LLM adapter for the analysis call.\n * @param opts - Model and actor options.\n * @returns `Node<StrategyPlan | null>` — emits the latest plan, or `null`\n * while inputs are unsettled.\n */\nexport function suggestStrategyReactive(\n\tgraph: Node<Graph | null>,\n\tproblem: NodeInput<string>,\n\tadapter: LLMAdapter,\n\topts?: SuggestStrategyOptions,\n): Node<StrategyPlan | null> {\n\tconst problemNode = fromAny(problem);\n\t// problem is primary (re-triggers on change); graph is sampled — no\n\t// graph-edit-feedback loop to suggestStrategy when callers apply ops.\n\tconst paired = withLatestFrom(problemNode as Node<unknown>, graph as Node<unknown>);\n\treturn switchMap<unknown, StrategyPlan | null>(paired, (pair) => {\n\t\tif (pair == null) return node<StrategyPlan | null>([], { initial: null });\n\t\tconst [pText, g] = pair as [string | null, Graph | null];\n\t\tif (!g || !pText || typeof pText !== \"string\" || pText.trim().length === 0) {\n\t\t\treturn node<StrategyPlan | null>([], { initial: null });\n\t\t}\n\t\t// QA-fix: skip rather than ERROR if the sampled Graph was destroyed\n\t\t// between the `withLatestFrom` sample and this project fn. Common when\n\t\t// a caller's reactive `graph: Node<Graph | null>` cycles graphs faster\n\t\t// than `suggestStrategy` resolves; the supersede was the user's intent,\n\t\t// so emitting null here matches \"input not ready\" semantics rather\n\t\t// than surfacing a spurious ERROR on the StrategyPlan stream.\n\t\tif (g.destroyed) return node<StrategyPlan | null>([], { initial: null });\n\t\treturn node<StrategyPlan | null>(\n\t\t\t(_data, actions) => {\n\t\t\t\tconst controller = new AbortController();\n\t\t\t\tlet cancelled = false;\n\t\t\t\tsuggestStrategy(g, pText, adapter, { ...opts, signal: controller.signal })\n\t\t\t\t\t.then((plan) => {\n\t\t\t\t\t\tif (cancelled) return;\n\t\t\t\t\t\tactions.emit(plan);\n\t\t\t\t\t\tactions.down([[COMPLETE]]);\n\t\t\t\t\t})\n\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\tif (cancelled) return;\n\t\t\t\t\t\tactions.down([[ERROR, err]]);\n\t\t\t\t\t});\n\t\t\t\treturn () => {\n\t\t\t\t\tcancelled = true;\n\t\t\t\t\tcontroller.abort();\n\t\t\t\t};\n\t\t\t},\n\t\t\t{ describeKind: \"producer\", ...{ name: \"suggestStrategy::call\" } },\n\t\t);\n\t});\n}\n","// ---------------------------------------------------------------------------\n// validateGraphDef\n// ---------------------------------------------------------------------------\n\n/** Validation result from {@link validateGraphDef}. */\nexport type GraphDefValidation = {\n\treadonly valid: boolean;\n\treadonly errors: readonly string[];\n};\n\nconst VALID_NODE_TYPES = new Set([\"state\", \"derived\", \"producer\", \"operator\", \"effect\"]);\n\n/**\n * Validate an LLM-generated graph definition before passing to\n * `Graph.fromSnapshot()`.\n *\n * Checks:\n * - Required fields: `name`, `nodes`, `edges`\n * - Node types are valid enum values\n * - Edge `from`/`to` reference existing nodes\n * - No duplicate edge entries\n *\n * @param def - The graph definition to validate (parsed JSON).\n * @returns Validation result with errors array.\n */\nexport function validateGraphDef(def: unknown): GraphDefValidation {\n\tconst errors: string[] = [];\n\n\tif (def == null || typeof def !== \"object\") {\n\t\treturn { valid: false, errors: [\"Definition must be a non-null object\"] };\n\t}\n\n\tconst d = def as Record<string, unknown>;\n\n\tif (typeof d.name !== \"string\" || d.name.length === 0) {\n\t\terrors.push(\"Missing or empty 'name' field\");\n\t}\n\n\tif (d.nodes == null || typeof d.nodes !== \"object\" || Array.isArray(d.nodes)) {\n\t\terrors.push(\"Missing or invalid 'nodes' field (must be an object)\");\n\t\treturn { valid: false, errors };\n\t}\n\n\tconst nodeNames = new Set(Object.keys(d.nodes as object));\n\n\tfor (const [name, raw] of Object.entries(d.nodes as Record<string, unknown>)) {\n\t\tif (raw == null || typeof raw !== \"object\") {\n\t\t\terrors.push(`Node \"${name}\": must be an object`);\n\t\t\tcontinue;\n\t\t}\n\t\tconst node = raw as Record<string, unknown>;\n\t\tif (typeof node.type !== \"string\" || !VALID_NODE_TYPES.has(node.type)) {\n\t\t\terrors.push(\n\t\t\t\t`Node \"${name}\": invalid type \"${String(node.type)}\" (expected: ${[...VALID_NODE_TYPES].join(\", \")})`,\n\t\t\t);\n\t\t}\n\t\tif (Array.isArray(node.deps)) {\n\t\t\tfor (const dep of node.deps) {\n\t\t\t\tif (typeof dep === \"string\" && !nodeNames.has(dep)) {\n\t\t\t\t\terrors.push(`Node \"${name}\": dep \"${dep}\" does not reference an existing node`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!Array.isArray(d.edges)) {\n\t\tif (d.edges !== undefined) {\n\t\t\terrors.push(\"'edges' must be an array\");\n\t\t}\n\t\t// edges are optional — no error if absent\n\t} else {\n\t\tconst seen = new Set<string>();\n\t\tfor (let i = 0; i < (d.edges as unknown[]).length; i++) {\n\t\t\tconst edge = (d.edges as unknown[])[i];\n\t\t\tif (edge == null || typeof edge !== \"object\") {\n\t\t\t\terrors.push(`Edge [${i}]: must be an object`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst e = edge as Record<string, unknown>;\n\t\t\tif (typeof e.from !== \"string\" || !nodeNames.has(e.from)) {\n\t\t\t\terrors.push(`Edge [${i}]: 'from' \"${String(e.from)}\" does not reference an existing node`);\n\t\t\t}\n\t\t\tif (typeof e.to !== \"string\" || !nodeNames.has(e.to)) {\n\t\t\t\terrors.push(`Edge [${i}]: 'to' \"${String(e.to)}\" does not reference an existing node`);\n\t\t\t}\n\t\t\tconst key = `${e.from}->${e.to}`;\n\t\t\tif (seen.has(key)) {\n\t\t\t\terrors.push(`Edge [${i}]: duplicate edge ${key}`);\n\t\t\t}\n\t\t\tseen.add(key);\n\t\t}\n\t}\n\n\treturn { valid: errors.length === 0, errors };\n}\n"],"mappings":"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","names":["batch","node","node","batch","monotonicNs","node","keepalive","reactiveLog","reactiveLog","node","batch","keepalive","monotonicNs","fromAny","keepalive","fromAny","keepalive","fromAny","fromAny","fromAny","fromAny","ResettableTimer","fromAny","ResettableTimer","fromAny","fromAny","fromAny","factoryTag","node","wallClockNs","fromAny","keepalive","wallClockNs","node","store","batch","fromAny","factoryTag","keepalive","node","fromAny","keepalive","node","fromAny","batch","keepalive","node","node","store","batch","node","node","batch","node","node","batch","node","node","batch","i","node","batch","node","batch","factoryTag","node","fromAny","switchMap","batch","factoryTag","node","fromAny","fromAny","node","batch","factoryTag","node","node","fromAny","switchMap","fromAny","switchMap","node","node","COMPLETE","ERROR","node","fromAny","switchMap","fromAny","switchMap","node","COMPLETE","ERROR","node"]}