@demlik/tea 0.13.0 → 0.14.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 (372) hide show
  1. package/README.md +11 -9
  2. package/dist/agent/index.d.ts +637 -45
  3. package/dist/agent/index.js +9 -19
  4. package/dist/{chunk-25LBDCBC.js → chunk-6IQPODUF.js} +2 -2
  5. package/dist/{chunk-25LBDCBC.js.map → chunk-6IQPODUF.js.map} +1 -1
  6. package/dist/chunk-AQ6ZIMEA.js +421 -0
  7. package/dist/chunk-AQ6ZIMEA.js.map +1 -0
  8. package/dist/{chunk-MUUROGIH.js → chunk-BLJ2JQSH.js} +62 -12
  9. package/dist/chunk-BLJ2JQSH.js.map +1 -0
  10. package/dist/{chunk-RH5EFRVJ.js → chunk-F2US5BW6.js} +25 -5
  11. package/dist/chunk-F2US5BW6.js.map +1 -0
  12. package/dist/{batch-window/index.js → chunk-F7FMAWLA.js} +4 -8
  13. package/dist/chunk-F7FMAWLA.js.map +1 -0
  14. package/dist/{chunk-O4MVQTEJ.js → chunk-HUKZQX6U.js} +20 -16
  15. package/dist/chunk-HUKZQX6U.js.map +1 -0
  16. package/dist/{chunk-EWJP3YYP.js → chunk-HWVW4AXC.js} +3 -3
  17. package/dist/chunk-HWVW4AXC.js.map +1 -0
  18. package/dist/{chunk-DMYGQB4O.js → chunk-HYDWG35Q.js} +23 -6
  19. package/dist/chunk-HYDWG35Q.js.map +1 -0
  20. package/dist/{chunk-YUXP55T2.js → chunk-I5MQMJDW.js} +57 -7
  21. package/dist/chunk-I5MQMJDW.js.map +1 -0
  22. package/dist/{chunk-J6527VRQ.js → chunk-LFZUK6J2.js} +3 -3
  23. package/dist/chunk-LFZUK6J2.js.map +1 -0
  24. package/dist/{chunk-ZVJZ72HY.js → chunk-LYLTKJWM.js} +25 -11
  25. package/dist/chunk-LYLTKJWM.js.map +1 -0
  26. package/dist/{chunk-D736QUGF.js → chunk-MYXFNWAJ.js} +4 -5
  27. package/dist/chunk-MYXFNWAJ.js.map +1 -0
  28. package/dist/{chunk-K575PT4S.js → chunk-PR6TB3BL.js} +15 -4
  29. package/dist/chunk-PR6TB3BL.js.map +1 -0
  30. package/dist/chunk-RQULHGYH.js +1804 -0
  31. package/dist/chunk-RQULHGYH.js.map +1 -0
  32. package/dist/{chunk-FV3Z5MBE.js → chunk-TXN2KFHF.js} +14 -4
  33. package/dist/chunk-TXN2KFHF.js.map +1 -0
  34. package/dist/{chunk-Q2UM7BXU.js → chunk-VBDU4JL6.js} +2 -2
  35. package/dist/chunk-VBDU4JL6.js.map +1 -0
  36. package/dist/chunk-Z2L3LSNV.js +1470 -0
  37. package/dist/chunk-Z2L3LSNV.js.map +1 -0
  38. package/dist/{core-Co0LWkIA.d.ts → core-CTzMJ82M.d.ts} +72 -23
  39. package/dist/devtools/index.d.ts +2 -2
  40. package/dist/devtools/index.js +207 -2
  41. package/dist/devtools/index.js.map +1 -1
  42. package/dist/do/index.d.ts +42 -29
  43. package/dist/do/index.js +36 -25
  44. package/dist/do/index.js.map +1 -1
  45. package/dist/{durable-effects-C6uwzjb5.d.ts → durable-effects-B0-qGQDy.d.ts} +2 -2
  46. package/dist/extension/index.d.ts +300 -3
  47. package/dist/extension/index.js +596 -5
  48. package/dist/extension/index.js.map +1 -1
  49. package/dist/flow/index.d.ts +1295 -0
  50. package/dist/flow/index.js +732 -0
  51. package/dist/flow/index.js.map +1 -0
  52. package/dist/idempotency/index.d.ts +90 -116
  53. package/dist/idempotency/index.js +4 -1
  54. package/dist/{batch-window/index.d.ts → index-4vZzljCD.d.ts} +7 -12
  55. package/dist/{fan-out/index.d.ts → index-6A7dB8f6.d.ts} +7 -9
  56. package/dist/index-B5BZ-_cT.d.ts +616 -0
  57. package/dist/index-Bc40JWVl.d.ts +131 -0
  58. package/dist/{debounce/index.d.ts → index-DHSUmQTR.d.ts} +7 -7
  59. package/dist/index-DJWIER_3.d.ts +69 -0
  60. package/dist/{snapshot/index.d.ts → index-DMCeMPMJ.d.ts} +15 -78
  61. package/dist/{monitored-run/index.d.ts → index-NjrT3fL2.d.ts} +37 -13
  62. package/dist/{recorder/index.d.ts → index-TvRb1KVf.d.ts} +4 -7
  63. package/dist/{deadline/index.d.ts → index-q0hXFeZ0.d.ts} +155 -9
  64. package/dist/index.d.ts +711 -6
  65. package/dist/index.js +1 -2
  66. package/dist/jev/index.d.ts +634 -0
  67. package/dist/jev/index.js +433 -0
  68. package/dist/jev/index.js.map +1 -0
  69. package/dist/machine-CdIcN2Xm.d.ts +1773 -0
  70. package/dist/machine-viz/index.d.ts +1 -1
  71. package/dist/machine-viz/index.js +12 -5
  72. package/dist/machine-viz/index.js.map +1 -1
  73. package/dist/mem/index.d.ts +18 -3
  74. package/dist/mem/index.js +22 -2
  75. package/dist/mem/index.js.map +1 -1
  76. package/dist/node/index.d.ts +104 -6
  77. package/dist/node/index.js +132 -9
  78. package/dist/node/index.js.map +1 -1
  79. package/dist/{paginator → paginate}/index.d.ts +151 -6
  80. package/dist/paginate/index.js +7 -0
  81. package/dist/parity/index.d.ts +4 -10
  82. package/dist/parity/index.js +4 -7
  83. package/dist/parity/index.js.map +1 -1
  84. package/dist/pbt/index.d.ts +247 -5
  85. package/dist/pbt/index.js +124 -5
  86. package/dist/pbt/index.js.map +1 -1
  87. package/dist/{trace-replay → persistence}/index.d.ts +7 -5
  88. package/dist/persistence/index.js +6 -0
  89. package/dist/react/index.d.ts +2 -2
  90. package/dist/react/index.js +1 -2
  91. package/dist/react/index.js.map +1 -1
  92. package/dist/resilience/index.d.ts +743 -0
  93. package/dist/resilience/index.js +657 -0
  94. package/dist/resilience/index.js.map +1 -0
  95. package/dist/retry-backoff/index.d.ts +3 -2
  96. package/dist/retry-backoff/index.js +1 -1
  97. package/dist/runtime-types-LWDoi943.d.ts +998 -0
  98. package/dist/testing/index.d.ts +2 -2
  99. package/dist/testing/index.js +1 -2
  100. package/dist/testing/index.js.map +1 -1
  101. package/dist/{throttled-input → timing}/index.d.ts +143 -12
  102. package/dist/{throttled-input → timing}/index.js +57 -12
  103. package/dist/timing/index.js.map +1 -0
  104. package/dist/{types-XS_miRnB.d.ts → types-DP3f5NIl.d.ts} +1 -1
  105. package/dist/work-queue/index.d.ts +130 -54
  106. package/dist/work-queue/index.js +3 -2
  107. package/dist/work-queue/index.js.map +1 -1
  108. package/package.json +45 -218
  109. package/dist/authed-call/index.d.ts +0 -120
  110. package/dist/authed-call/index.js +0 -134
  111. package/dist/authed-call/index.js.map +0 -1
  112. package/dist/await-terminal/index.d.ts +0 -101
  113. package/dist/await-terminal/index.js +0 -76
  114. package/dist/await-terminal/index.js.map +0 -1
  115. package/dist/batch-window/index.js.map +0 -1
  116. package/dist/cache/index.d.ts +0 -152
  117. package/dist/cache/index.js +0 -8
  118. package/dist/chart/index.d.ts +0 -218
  119. package/dist/chart/index.js +0 -16
  120. package/dist/chart/index.js.map +0 -1
  121. package/dist/chart/inspect/index.d.ts +0 -86
  122. package/dist/chart/inspect/index.js +0 -5
  123. package/dist/chart/inspect/react.d.ts +0 -113
  124. package/dist/chart/inspect/react.js +0 -11
  125. package/dist/chart/inspect/react.js.map +0 -1
  126. package/dist/chart/inspect/styles.css +0 -286
  127. package/dist/chart/lane/index.d.ts +0 -362
  128. package/dist/chart/lane/index.js +0 -9
  129. package/dist/chart/lane/index.js.map +0 -1
  130. package/dist/chart/lane/react.d.ts +0 -84
  131. package/dist/chart/lane/react.js +0 -559
  132. package/dist/chart/lane/react.js.map +0 -1
  133. package/dist/chart/lane/server.d.ts +0 -148
  134. package/dist/chart/lane/server.js +0 -209
  135. package/dist/chart/lane/server.js.map +0 -1
  136. package/dist/chart/lane/styles.css +0 -498
  137. package/dist/chart/lane/viewer/assets/abnfDiagram-N423BO3Z-C729LI31.js +0 -1
  138. package/dist/chart/lane/viewer/assets/architectureDiagram-T3A2C74G-C729LI31.js +0 -1
  139. package/dist/chart/lane/viewer/assets/blockDiagram-VBNYF7ZC-C729LI31.js +0 -1
  140. package/dist/chart/lane/viewer/assets/c4Diagram-5PPSVZJV-C729LI31.js +0 -1
  141. package/dist/chart/lane/viewer/assets/chunk-2GRJ4B5K-HdDf8SI3.js +0 -1
  142. package/dist/chart/lane/viewer/assets/chunk-5RXB4S5H-CcNtpUd7.js +0 -231
  143. package/dist/chart/lane/viewer/assets/chunk-5VM5RSS4-BP4fRS_5.js +0 -15
  144. package/dist/chart/lane/viewer/assets/chunk-KBJHAD2P-DZOw7xU6.js +0 -1
  145. package/dist/chart/lane/viewer/assets/chunk-NSK5VX7P-CBCyTZMs.js +0 -128
  146. package/dist/chart/lane/viewer/assets/classDiagram-JCYQIIEL-C729LI31.js +0 -1
  147. package/dist/chart/lane/viewer/assets/classDiagram-v2-OCEON4UE-D4uAiFr8.js +0 -206
  148. package/dist/chart/lane/viewer/assets/cose-bilkent-JH36ORCC-DOwCrGXH.js +0 -1
  149. package/dist/chart/lane/viewer/assets/cynefinDiagram-MW4NZA55-C729LI31.js +0 -1
  150. package/dist/chart/lane/viewer/assets/dagre-K_PewWfS.js +0 -1
  151. package/dist/chart/lane/viewer/assets/dagre-VZM6K2ZE-831qZcA8.js +0 -4
  152. package/dist/chart/lane/viewer/assets/diagram-7IWD3JNH-C729LI31.js +0 -1
  153. package/dist/chart/lane/viewer/assets/diagram-B4RE2ZJO-C729LI31.js +0 -1
  154. package/dist/chart/lane/viewer/assets/diagram-LBJQPF4R-C729LI31.js +0 -1
  155. package/dist/chart/lane/viewer/assets/diagram-Q27KOJAE-C729LI31.js +0 -1
  156. package/dist/chart/lane/viewer/assets/diagram-UB23O5K3-C729LI31.js +0 -1
  157. package/dist/chart/lane/viewer/assets/ebnfDiagram-BXEA7PRR-C729LI31.js +0 -1
  158. package/dist/chart/lane/viewer/assets/erDiagram-JOGREHBK-C729LI31.js +0 -1
  159. package/dist/chart/lane/viewer/assets/flowDiagram-UKHOOZJN-C729LI31.js +0 -1
  160. package/dist/chart/lane/viewer/assets/ganttDiagram-PKOTCBZU-C729LI31.js +0 -1
  161. package/dist/chart/lane/viewer/assets/gitGraphDiagram-DS77QQ5N-C729LI31.js +0 -1
  162. package/dist/chart/lane/viewer/assets/index-9SkH5NA3.css +0 -1
  163. package/dist/chart/lane/viewer/assets/index-Bgt4sXpW.js +0 -195
  164. package/dist/chart/lane/viewer/assets/infoDiagram-6WML65LV-C729LI31.js +0 -1
  165. package/dist/chart/lane/viewer/assets/ishikawaDiagram-WSZJBQD7-C729LI31.js +0 -1
  166. package/dist/chart/lane/viewer/assets/journeyDiagram-NVQOT4AX-C729LI31.js +0 -1
  167. package/dist/chart/lane/viewer/assets/kanban-definition-27J2QSJJ-G7PaPzy-.js +0 -89
  168. package/dist/chart/lane/viewer/assets/katex-DOwCrGXH.js +0 -1
  169. package/dist/chart/lane/viewer/assets/mindmap-definition-FAOFIHXS-CGj9nrVk.js +0 -96
  170. package/dist/chart/lane/viewer/assets/path-fybaL0A-.js +0 -1
  171. package/dist/chart/lane/viewer/assets/pegDiagram-VL7TDLO6-C729LI31.js +0 -1
  172. package/dist/chart/lane/viewer/assets/pieDiagram-7S7Q4E2Y-C729LI31.js +0 -1
  173. package/dist/chart/lane/viewer/assets/quadrantDiagram-CIZ2JOQS-C729LI31.js +0 -1
  174. package/dist/chart/lane/viewer/assets/railroadDiagram-AXF67PYL-C729LI31.js +0 -1
  175. package/dist/chart/lane/viewer/assets/requirementDiagram-LRYGKXZP-C729LI31.js +0 -1
  176. package/dist/chart/lane/viewer/assets/sankeyDiagram-W5VNT64P-C729LI31.js +0 -1
  177. package/dist/chart/lane/viewer/assets/sequenceDiagram-SI44F4Z6-C729LI31.js +0 -1
  178. package/dist/chart/lane/viewer/assets/stateDiagram-OKZ733FA-B_88AzBS.js +0 -1
  179. package/dist/chart/lane/viewer/assets/stateDiagram-v2-UEYNNEHI-CR5gcgq6.js +0 -1
  180. package/dist/chart/lane/viewer/assets/swimlanes-SLNWSIFB-B4xK-rwg.js +0 -1
  181. package/dist/chart/lane/viewer/assets/swimlanesDiagram-ULZ7WXOC-C729LI31.js +0 -1
  182. package/dist/chart/lane/viewer/assets/timeline-definition-Z64GVDOM-CCv52MfY.js +0 -120
  183. package/dist/chart/lane/viewer/assets/vennDiagram-T6HMQDX7-C729LI31.js +0 -1
  184. package/dist/chart/lane/viewer/assets/wardleyDiagram-T6FBY63Y-C729LI31.js +0 -1
  185. package/dist/chart/lane/viewer/assets/xychartDiagram-ELKLHX3M-C729LI31.js +0 -1
  186. package/dist/chart/lane/viewer/index.html +0 -15
  187. package/dist/chart/report/index.d.ts +0 -117
  188. package/dist/chart/report/index.js +0 -32
  189. package/dist/chart/report/index.js.map +0 -1
  190. package/dist/chunk-2YFLOCWX.js +0 -15
  191. package/dist/chunk-2YFLOCWX.js.map +0 -1
  192. package/dist/chunk-3I52QZZ5.js +0 -519
  193. package/dist/chunk-3I52QZZ5.js.map +0 -1
  194. package/dist/chunk-3ZAFFRRB.js +0 -457
  195. package/dist/chunk-3ZAFFRRB.js.map +0 -1
  196. package/dist/chunk-4EQZ76JC.js +0 -33
  197. package/dist/chunk-4EQZ76JC.js.map +0 -1
  198. package/dist/chunk-4KLG43GY.js +0 -223
  199. package/dist/chunk-4KLG43GY.js.map +0 -1
  200. package/dist/chunk-7FRZ2CT2.js +0 -424
  201. package/dist/chunk-7FRZ2CT2.js.map +0 -1
  202. package/dist/chunk-AZZLE7XR.js +0 -62
  203. package/dist/chunk-AZZLE7XR.js.map +0 -1
  204. package/dist/chunk-BYQUGDD3.js +0 -16
  205. package/dist/chunk-BYQUGDD3.js.map +0 -1
  206. package/dist/chunk-CIQG5L42.js +0 -685
  207. package/dist/chunk-CIQG5L42.js.map +0 -1
  208. package/dist/chunk-CLM6ERNO.js +0 -61
  209. package/dist/chunk-CLM6ERNO.js.map +0 -1
  210. package/dist/chunk-COS5MSTO.js +0 -88
  211. package/dist/chunk-COS5MSTO.js.map +0 -1
  212. package/dist/chunk-CRPZJVD2.js +0 -71
  213. package/dist/chunk-CRPZJVD2.js.map +0 -1
  214. package/dist/chunk-D62FDQKE.js +0 -53
  215. package/dist/chunk-D62FDQKE.js.map +0 -1
  216. package/dist/chunk-D736QUGF.js.map +0 -1
  217. package/dist/chunk-DGE4PV4A.js +0 -26
  218. package/dist/chunk-DGE4PV4A.js.map +0 -1
  219. package/dist/chunk-DMYGQB4O.js.map +0 -1
  220. package/dist/chunk-EWJP3YYP.js.map +0 -1
  221. package/dist/chunk-FV3Z5MBE.js.map +0 -1
  222. package/dist/chunk-HCEVHFJ7.js +0 -54
  223. package/dist/chunk-HCEVHFJ7.js.map +0 -1
  224. package/dist/chunk-J6527VRQ.js.map +0 -1
  225. package/dist/chunk-JELSZN25.js +0 -47
  226. package/dist/chunk-JELSZN25.js.map +0 -1
  227. package/dist/chunk-K575PT4S.js.map +0 -1
  228. package/dist/chunk-L57ZOT5K.js +0 -184
  229. package/dist/chunk-L57ZOT5K.js.map +0 -1
  230. package/dist/chunk-MU6MCIAC.js +0 -15
  231. package/dist/chunk-MU6MCIAC.js.map +0 -1
  232. package/dist/chunk-MUUROGIH.js.map +0 -1
  233. package/dist/chunk-NR7BU22N.js +0 -758
  234. package/dist/chunk-NR7BU22N.js.map +0 -1
  235. package/dist/chunk-O4MVQTEJ.js.map +0 -1
  236. package/dist/chunk-OOYD44JI.js +0 -317
  237. package/dist/chunk-OOYD44JI.js.map +0 -1
  238. package/dist/chunk-Q2UM7BXU.js.map +0 -1
  239. package/dist/chunk-RH5EFRVJ.js.map +0 -1
  240. package/dist/chunk-S2EGRPCM.js +0 -47
  241. package/dist/chunk-S2EGRPCM.js.map +0 -1
  242. package/dist/chunk-SINXE47Y.js +0 -55
  243. package/dist/chunk-SINXE47Y.js.map +0 -1
  244. package/dist/chunk-UF4MZSLT.js +0 -53
  245. package/dist/chunk-UF4MZSLT.js.map +0 -1
  246. package/dist/chunk-UOC2PL46.js +0 -13
  247. package/dist/chunk-UOC2PL46.js.map +0 -1
  248. package/dist/chunk-VYFAZN3F.js +0 -372
  249. package/dist/chunk-VYFAZN3F.js.map +0 -1
  250. package/dist/chunk-WRAA7GVZ.js +0 -209
  251. package/dist/chunk-WRAA7GVZ.js.map +0 -1
  252. package/dist/chunk-XGELA764.js +0 -163
  253. package/dist/chunk-XGELA764.js.map +0 -1
  254. package/dist/chunk-YUXP55T2.js.map +0 -1
  255. package/dist/chunk-YWIKDKHY.js +0 -307
  256. package/dist/chunk-YWIKDKHY.js.map +0 -1
  257. package/dist/chunk-ZJ5AOYBH.js +0 -8
  258. package/dist/chunk-ZJ5AOYBH.js.map +0 -1
  259. package/dist/chunk-ZSUUOEPL.js +0 -731
  260. package/dist/chunk-ZSUUOEPL.js.map +0 -1
  261. package/dist/chunk-ZVJZ72HY.js.map +0 -1
  262. package/dist/circuit-breaker/index.d.ts +0 -197
  263. package/dist/circuit-breaker/index.js +0 -3
  264. package/dist/circuit-breaker/index.js.map +0 -1
  265. package/dist/deadline/index.js +0 -6
  266. package/dist/deadline/index.js.map +0 -1
  267. package/dist/debounce/index.js +0 -3
  268. package/dist/debounce/index.js.map +0 -1
  269. package/dist/extension/react.d.ts +0 -121
  270. package/dist/extension/react.js +0 -75
  271. package/dist/extension/react.js.map +0 -1
  272. package/dist/extension/subs/index.d.ts +0 -45
  273. package/dist/extension/subs/index.js +0 -80
  274. package/dist/extension/subs/index.js.map +0 -1
  275. package/dist/extension/test-utils.d.ts +0 -128
  276. package/dist/extension/test-utils.js +0 -277
  277. package/dist/extension/test-utils.js.map +0 -1
  278. package/dist/fan-out/index.js +0 -5
  279. package/dist/fan-out/index.js.map +0 -1
  280. package/dist/fold-BJPdjc9w.d.ts +0 -435
  281. package/dist/graph-B3L5e0N1.d.ts +0 -923
  282. package/dist/idempotency/adapter.d.ts +0 -62
  283. package/dist/idempotency/adapter.js +0 -4
  284. package/dist/idempotency/adapter.js.map +0 -1
  285. package/dist/idempotent-intake/index.d.ts +0 -188
  286. package/dist/idempotent-intake/index.js +0 -7
  287. package/dist/idempotent-intake/index.js.map +0 -1
  288. package/dist/journal/index.d.ts +0 -373
  289. package/dist/journal/index.js +0 -3
  290. package/dist/journal/index.js.map +0 -1
  291. package/dist/llm-call/index.d.ts +0 -311
  292. package/dist/llm-call/index.js +0 -16
  293. package/dist/llm-call/index.js.map +0 -1
  294. package/dist/machine-BtFWQmmq.d.ts +0 -804
  295. package/dist/monitored-run/index.js +0 -10
  296. package/dist/monitored-run/index.js.map +0 -1
  297. package/dist/paginated-walk/index.d.ts +0 -235
  298. package/dist/paginated-walk/index.js +0 -16
  299. package/dist/paginated-walk/index.js.map +0 -1
  300. package/dist/paginator/index.js +0 -3
  301. package/dist/paginator/index.js.map +0 -1
  302. package/dist/pbt/arbitraries/index.d.ts +0 -136
  303. package/dist/pbt/arbitraries/index.js +0 -3
  304. package/dist/pbt/arbitraries/index.js.map +0 -1
  305. package/dist/pbt/runners/index.d.ts +0 -118
  306. package/dist/pbt/runners/index.js +0 -5
  307. package/dist/pbt/runners/index.js.map +0 -1
  308. package/dist/poller/index.d.ts +0 -352
  309. package/dist/poller/index.js +0 -115
  310. package/dist/poller/index.js.map +0 -1
  311. package/dist/prediction/index.d.ts +0 -131
  312. package/dist/prediction/index.js +0 -4
  313. package/dist/prediction/index.js.map +0 -1
  314. package/dist/protocol-B5YmJr0d.d.ts +0 -45
  315. package/dist/pure/index.d.ts +0 -3
  316. package/dist/pure/index.js +0 -4
  317. package/dist/pure/index.js.map +0 -1
  318. package/dist/rate-limit/index.d.ts +0 -115
  319. package/dist/rate-limit/index.js +0 -3
  320. package/dist/rate-limit/index.js.map +0 -1
  321. package/dist/reconciler/index.d.ts +0 -193
  322. package/dist/reconciler/index.js +0 -164
  323. package/dist/reconciler/index.js.map +0 -1
  324. package/dist/recorder/index.js +0 -3
  325. package/dist/recorder/index.js.map +0 -1
  326. package/dist/reducer-4GNR6b8B.d.ts +0 -447
  327. package/dist/resilient-call/index.d.ts +0 -320
  328. package/dist/resilient-call/index.js +0 -14
  329. package/dist/resilient-call/index.js.map +0 -1
  330. package/dist/retry-to-success/index.d.ts +0 -109
  331. package/dist/retry-to-success/index.js +0 -37
  332. package/dist/retry-to-success/index.js.map +0 -1
  333. package/dist/run-pAcmBpah.d.ts +0 -713
  334. package/dist/runtime-types-CNLmhWif.d.ts +0 -517
  335. package/dist/saga/index.d.ts +0 -241
  336. package/dist/saga/index.js +0 -150
  337. package/dist/saga/index.js.map +0 -1
  338. package/dist/samples-B3My5oh2.d.ts +0 -59
  339. package/dist/snapshot/index.js +0 -5
  340. package/dist/snapshot/index.js.map +0 -1
  341. package/dist/subs/index.d.ts +0 -472
  342. package/dist/subs/index.js +0 -7
  343. package/dist/subs/index.js.map +0 -1
  344. package/dist/throttle/index.d.ts +0 -134
  345. package/dist/throttle/index.js +0 -3
  346. package/dist/throttle/index.js.map +0 -1
  347. package/dist/throttled-input/index.js.map +0 -1
  348. package/dist/token-refresh/index.d.ts +0 -216
  349. package/dist/token-refresh/index.js +0 -6
  350. package/dist/token-refresh/index.js.map +0 -1
  351. package/dist/trace-replay/index.js +0 -6
  352. package/dist/trace-replay/index.js.map +0 -1
  353. package/dist/with-deadline/index.d.ts +0 -197
  354. package/dist/with-deadline/index.js +0 -111
  355. package/dist/with-deadline/index.js.map +0 -1
  356. package/dist/with-resilience/index.d.ts +0 -225
  357. package/dist/with-resilience/index.js +0 -240
  358. package/dist/with-resilience/index.js.map +0 -1
  359. package/dist/with-telemetry/index.d.ts +0 -150
  360. package/dist/with-telemetry/index.js +0 -70
  361. package/dist/with-telemetry/index.js.map +0 -1
  362. package/dist/work-queue/adapter.d.ts +0 -84
  363. package/dist/work-queue/adapter.js +0 -4
  364. package/dist/work-queue/adapter.js.map +0 -1
  365. package/dist/work-queue/ops.d.ts +0 -71
  366. package/dist/work-queue/ops.js +0 -3
  367. package/dist/work-queue/ops.js.map +0 -1
  368. package/dist/workflow/index.d.ts +0 -485
  369. package/dist/workflow/index.js +0 -244
  370. package/dist/workflow/index.js.map +0 -1
  371. /package/dist/{cache → paginate}/index.js.map +0 -0
  372. /package/dist/{chart/inspect → persistence}/index.js.map +0 -0
@@ -0,0 +1,433 @@
1
+ import { createBatchWindow, subscribeBatchWindow } from '../chunk-F7FMAWLA.js';
2
+ import '../chunk-LFZUK6J2.js';
3
+ import { createFanOut } from '../chunk-MYXFNWAJ.js';
4
+ import '../chunk-TXN2KFHF.js';
5
+ import { runCmdDef, createResilientCall, liftResilience, MsgType } from '../chunk-AQ6ZIMEA.js';
6
+ import '../chunk-VBDU4JL6.js';
7
+ import { initCache, has, set, evictExpired, get, cacheEvictionSub, cacheEvictionSubscribe } from '../chunk-F2US5BW6.js';
8
+ export { deadlineSub, subscribeDeadline } from '../chunk-F2US5BW6.js';
9
+ import { describeError } from '../chunk-G5E74IJB.js';
10
+ import '../chunk-RQULHGYH.js';
11
+
12
+ // src/internal/jev/protocol/index.ts
13
+ var jevQuestions = (questions) => questions;
14
+ var JEV_ENDPOINT = "https://api.typesafe.ai/v1/systemone";
15
+ var JEV_ERR_TAG_WITNESS = {
16
+ malformed_body: true,
17
+ missing_answer: true,
18
+ answer_type_mismatch: true,
19
+ off_criteria_choice: true,
20
+ off_criteria_probabilities: true,
21
+ malformed_answer: true
22
+ };
23
+ var JEV_ERR_TAGS = new Set(
24
+ Object.keys(JEV_ERR_TAG_WITNESS)
25
+ );
26
+ function isJevErr(value) {
27
+ if (!("_tag" in value)) return false;
28
+ const tag = value._tag;
29
+ const tags = JEV_ERR_TAGS;
30
+ return typeof tag === "string" && tags.has(tag);
31
+ }
32
+ var isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
33
+ var isNum = (v) => typeof v === "number" && Number.isFinite(v);
34
+ var isNumMap = (v) => isObj(v) && Object.values(v).every(isNum);
35
+ var isStrMap = (v) => isObj(v) && Object.values(v).every((x) => typeof x === "string");
36
+ var err = (error) => ({
37
+ ok: false,
38
+ error
39
+ });
40
+ var checkAnswer = (id, question, answer) => {
41
+ if (!isObj(answer)) {
42
+ return { _tag: "malformed_answer", id, reason: "answer is not an object" };
43
+ }
44
+ const received = answer["type"];
45
+ if (typeof received !== "string") {
46
+ return { _tag: "malformed_answer", id, reason: "answer has no `type`" };
47
+ }
48
+ if (received !== question.type) {
49
+ return {
50
+ _tag: "answer_type_mismatch",
51
+ id,
52
+ expected: question.type,
53
+ received
54
+ };
55
+ }
56
+ if (question.type === "noul") {
57
+ return isNum(answer["noul"]) ? void 0 : { _tag: "malformed_answer", id, reason: "`noul` is not a number" };
58
+ }
59
+ if (!isNum(answer["confidence"])) {
60
+ return {
61
+ _tag: "malformed_answer",
62
+ id,
63
+ reason: "`confidence` is not a number"
64
+ };
65
+ }
66
+ const probabilities = answer["probabilities"];
67
+ if (!isNumMap(probabilities)) {
68
+ return {
69
+ _tag: "malformed_answer",
70
+ id,
71
+ reason: "`probabilities` is not a map of numbers"
72
+ };
73
+ }
74
+ if (question.type === "score") {
75
+ if (!isNum(answer["score"])) {
76
+ return {
77
+ _tag: "malformed_answer",
78
+ id,
79
+ reason: "`score` is not a number"
80
+ };
81
+ }
82
+ return isStrMap(answer["legend"]) ? void 0 : {
83
+ _tag: "malformed_answer",
84
+ id,
85
+ reason: "`legend` is not a map of strings"
86
+ };
87
+ }
88
+ const choice = answer["choice"];
89
+ if (typeof choice !== "string") {
90
+ return { _tag: "malformed_answer", id, reason: "`choice` is not a string" };
91
+ }
92
+ const options = Object.keys(question.criteria);
93
+ if (!options.includes(choice)) {
94
+ return { _tag: "off_criteria_choice", id, choice, options };
95
+ }
96
+ const missing = options.filter((k) => !Object.hasOwn(probabilities, k));
97
+ const extra = Object.keys(probabilities).filter((k) => !options.includes(k));
98
+ return missing.length === 0 && extra.length === 0 ? void 0 : { _tag: "off_criteria_probabilities", id, missing, extra, options };
99
+ };
100
+ var parseAnswers = (questions, body) => {
101
+ if (!isObj(body))
102
+ return err({ _tag: "malformed_body", reason: "body is not an object" });
103
+ const model = body["model"];
104
+ if (typeof model !== "string") {
105
+ return err({ _tag: "malformed_body", reason: "`model` is not a string" });
106
+ }
107
+ const usage = body["usage"];
108
+ if (!isObj(usage) || !isNum(usage["input_tokens"]) || !isNum(usage["output_tokens"])) {
109
+ return err({
110
+ _tag: "malformed_body",
111
+ reason: "`usage` is not `{ input_tokens, output_tokens }`"
112
+ });
113
+ }
114
+ const answers = body["answers"];
115
+ if (!isObj(answers)) {
116
+ return err({
117
+ _tag: "malformed_body",
118
+ reason: "`answers` is not an object"
119
+ });
120
+ }
121
+ for (const [id, question] of Object.entries(questions)) {
122
+ if (!Object.hasOwn(answers, id)) {
123
+ return err({ _tag: "missing_answer", id });
124
+ }
125
+ const bad = checkAnswer(id, question, answers[id]);
126
+ if (bad !== void 0) return err(bad);
127
+ }
128
+ return {
129
+ ok: true,
130
+ // Every id of `questions` passed `checkAnswer`, which is exactly the set of
131
+ // obligations `JevAnswers<Q>` states. `unknown` is the bridge because the
132
+ // per-id narrowing happened in a loop, where the compiler cannot carry it.
133
+ answers,
134
+ model,
135
+ usage: {
136
+ input_tokens: usage["input_tokens"],
137
+ output_tokens: usage["output_tokens"]
138
+ }
139
+ };
140
+ };
141
+ var classifyStatus = (status) => {
142
+ if (status >= 200 && status < 300) return "ok";
143
+ if (status === 429 || status === 529) return "retry";
144
+ return "terminal";
145
+ };
146
+
147
+ // src/internal/jev/ask/index.ts
148
+ function isTransientJevAskErr(error) {
149
+ return error._tag === "http_retry" || error._tag === "port_threw";
150
+ }
151
+ var JevAskFailure = class extends Error {
152
+ constructor(jev) {
153
+ super(`jev ask: ${jev._tag}`);
154
+ this.jev = jev;
155
+ this.name = "JevAskFailure";
156
+ }
157
+ jev;
158
+ };
159
+ function toAskErr(error) {
160
+ if (error instanceof JevAskFailure) return error.jev;
161
+ return { _tag: "port_threw", reason: describeError(error) };
162
+ }
163
+ var DEFAULT_JEV_MODEL = "jev-latest";
164
+ var NO_USAGE = { input_tokens: 0, output_tokens: 0 };
165
+ function jevAskCmdDef() {
166
+ return runCmdDef();
167
+ }
168
+ function createJevAsk(config, rng = Math.random) {
169
+ const resilientConfig = {
170
+ ...config.retry === void 0 ? {} : { retry: config.retry }
171
+ };
172
+ const rc = createResilientCall(resilientConfig, rng);
173
+ const model = config.model ?? DEFAULT_JEV_MODEL;
174
+ function isErrDecision(decided) {
175
+ return isJevErr(decided);
176
+ }
177
+ function liveRequest(s, key) {
178
+ const call = s.calls[key];
179
+ if (call?.phase === "running" || call?.phase === "waiting_retry") {
180
+ return call.input;
181
+ }
182
+ return void 0;
183
+ }
184
+ function init() {
185
+ return rc.init();
186
+ }
187
+ function attempt(s, key, content, at) {
188
+ const request = {
189
+ state: content,
190
+ model,
191
+ questions: config.questions
192
+ };
193
+ return rc.attempt(s, key, request, at);
194
+ }
195
+ function succeed(s, key, msg) {
196
+ return rc.succeed(s, key, msg);
197
+ }
198
+ function settleFromFallback(s, key, request, fallback, at) {
199
+ const decided = fallback(request);
200
+ if (isErrDecision(decided)) return rc.settleFailed(s, key, decided);
201
+ return rc.succeed(s, key, {
202
+ type: MsgType.ResilientOk,
203
+ key,
204
+ result: {
205
+ answers: decided,
206
+ model: request.model,
207
+ usage: NO_USAGE,
208
+ source: "fallback"
209
+ },
210
+ at
211
+ });
212
+ }
213
+ function fail(s, key, msg) {
214
+ if (!isTransientJevAskErr(msg.error)) {
215
+ return rc.settleFailed(s, key, msg.error);
216
+ }
217
+ const request = liveRequest(s, key);
218
+ const settled = rc.fail(s, key, msg);
219
+ const backedOff = settled[0].calls[key]?.phase !== "failed";
220
+ if (backedOff || config.fallback === void 0 || request === void 0) {
221
+ return settled;
222
+ }
223
+ return settleFromFallback(s, key, request, config.fallback, msg.at);
224
+ }
225
+ function onTimer(s, msg) {
226
+ return rc.onTimer(s, msg);
227
+ }
228
+ function subs(s) {
229
+ return rc.subs(s);
230
+ }
231
+ async function ask(request, signal) {
232
+ if (config.port === void 0) {
233
+ if (config.fallback === void 0) {
234
+ throw new JevAskFailure({ _tag: "no_answer_path" });
235
+ }
236
+ const decided = config.fallback(request);
237
+ if (isErrDecision(decided)) throw new JevAskFailure(decided);
238
+ return {
239
+ answers: decided,
240
+ model: request.model,
241
+ usage: NO_USAGE,
242
+ source: "fallback"
243
+ };
244
+ }
245
+ const { status, body } = await config.port(request, signal);
246
+ const kind = classifyStatus(status);
247
+ if (kind === "retry")
248
+ throw new JevAskFailure({ _tag: "http_retry", status });
249
+ if (kind === "terminal") {
250
+ throw new JevAskFailure({ _tag: "http_terminal", status });
251
+ }
252
+ const parsed = parseAnswers(config.questions, body);
253
+ if (!parsed.ok) throw new JevAskFailure(parsed.error);
254
+ return {
255
+ answers: parsed.answers,
256
+ model: parsed.model,
257
+ usage: parsed.usage,
258
+ source: "port"
259
+ };
260
+ }
261
+ const resilientRunHandler = rc.handlers({
262
+ run: (request) => ask(request)
263
+ }).resilient_run;
264
+ async function settleOf(cmd) {
265
+ const settle = await resilientRunHandler(cmd, {});
266
+ if (settle.type === MsgType.ResilientOk) return settle;
267
+ return {
268
+ type: MsgType.ResilientErr,
269
+ key: settle.key,
270
+ error: toAskErr(settle.error),
271
+ at: settle.at
272
+ };
273
+ }
274
+ function handlers() {
275
+ return { resilient_run: (cmd) => settleOf(cmd) };
276
+ }
277
+ return { init, attempt, succeed, fail, onTimer, subs, handlers, ask };
278
+ }
279
+ function liftJevAsk(state, result) {
280
+ return liftResilience(state, result);
281
+ }
282
+
283
+ // src/internal/jev/classify-batch/index.ts
284
+ var DEFAULT_CLASSIFY_MAX_ITEMS = 25;
285
+ function createClassifyBatch(config) {
286
+ const maxItems = config.maxItems ?? DEFAULT_CLASSIFY_MAX_ITEMS;
287
+ const askCmd = jevAskCmdDef();
288
+ const instructionsFor = config.instructions ?? ((key) => `Classify the element of \`state\` whose key is "${key}".`);
289
+ function idOfBatch(batch) {
290
+ return batch.id;
291
+ }
292
+ function questionsFor(items) {
293
+ const questions = {};
294
+ for (const item of items) {
295
+ const key = config.keyOf(item);
296
+ questions[key] = {
297
+ type: "choice",
298
+ instructions: instructionsFor(key, item),
299
+ criteria: config.criteria
300
+ };
301
+ }
302
+ return questions;
303
+ }
304
+ function requestFor(batch) {
305
+ return {
306
+ state: batch.items,
307
+ model: config.model ?? DEFAULT_JEV_MODEL,
308
+ questions: questionsFor(batch.items)
309
+ };
310
+ }
311
+ const fanOut = createFanOut({
312
+ concurrency: config.concurrency,
313
+ idOf: idOfBatch,
314
+ of: (batch) => askCmd({ key: batch.id, input: requestFor(batch) })
315
+ });
316
+ const window = createBatchWindow({
317
+ maxItems,
318
+ maxMs: config.maxMs,
319
+ flush: (items) => ({ type: "classify_batch_flush", items })
320
+ });
321
+ function init() {
322
+ return {
323
+ window: window.init(),
324
+ fanOut: fanOut.init(),
325
+ cache: initCache(),
326
+ failed: {}
327
+ };
328
+ }
329
+ function keysInFlight(state) {
330
+ const keys = /* @__PURE__ */ new Set();
331
+ for (const item of state.window.buffer) keys.add(config.keyOf(item));
332
+ for (const batch of state.fanOut.pending) {
333
+ for (const item of batch.items) keys.add(config.keyOf(item));
334
+ }
335
+ for (const batch of state.fanOut.running) {
336
+ for (const item of batch.items) keys.add(config.keyOf(item));
337
+ }
338
+ return keys;
339
+ }
340
+ function runningBatch(state, id) {
341
+ return state.fanOut.running.find((batch) => batch.id === id);
342
+ }
343
+ function scatter(state, flushed) {
344
+ if (flushed.length === 0) return [state, []];
345
+ const batches = flushed.map((cmd) => ({
346
+ id: cmd.items.map(config.keyOf).join("\0"),
347
+ items: cmd.items
348
+ }));
349
+ const [next, cmds] = fanOut.scatter(state.fanOut, batches);
350
+ return [{ ...state, fanOut: next }, cmds];
351
+ }
352
+ function add(state, item, at) {
353
+ const key = config.keyOf(item);
354
+ if (has(state.cache, key, at)) return [state, []];
355
+ if (keysInFlight(state).has(key)) return [state, []];
356
+ const failed = { ...state.failed };
357
+ delete failed[key];
358
+ const [nextWindow, flushed] = window.add(state.window, item, at);
359
+ return scatter({ ...state, failed, window: nextWindow }, flushed);
360
+ }
361
+ function onWindow(state, at) {
362
+ const [nextWindow, flushed] = window.onWindow(state.window, at);
363
+ return scatter({ ...state, window: nextWindow }, flushed);
364
+ }
365
+ function onBatchOk(state, msg) {
366
+ let cache = state.cache;
367
+ for (const [key, answer] of Object.entries(msg.result.answers)) {
368
+ cache = set(cache, key, answer, msg.at, config.ttlMs);
369
+ }
370
+ const failed = { ...state.failed };
371
+ for (const key of Object.keys(msg.result.answers)) delete failed[key];
372
+ const [nextFanOut, cmds] = fanOut.itemOk(state.fanOut, msg.key, msg.result);
373
+ return [{ ...state, cache, failed, fanOut: nextFanOut }, cmds];
374
+ }
375
+ function onBatchErr(state, msg) {
376
+ const batch = runningBatch(state, msg.key);
377
+ const failed = { ...state.failed };
378
+ if (batch !== void 0) {
379
+ for (const item of batch.items) failed[config.keyOf(item)] = msg.error;
380
+ }
381
+ const [nextFanOut, cmds] = fanOut.itemErr(state.fanOut, msg.key, msg.error);
382
+ return [{ ...state, failed, fanOut: nextFanOut }, cmds];
383
+ }
384
+ function onEvict(state, at) {
385
+ return [{ ...state, cache: evictExpired(state.cache, at) }, []];
386
+ }
387
+ function answerFor(state, key, at) {
388
+ const answer = get(state.cache, key, at);
389
+ if (answer !== void 0) return { status: "answered", answer };
390
+ const error = state.failed[key];
391
+ if (error !== void 0) return { status: "failed", error };
392
+ if (keysInFlight(state).has(key)) return { status: "pending" };
393
+ return { status: "absent" };
394
+ }
395
+ function subs(state, id = "jev-classify-batch") {
396
+ const windowSubs = window.subs(state.window, id);
397
+ if (config.evictEveryMs === void 0) return windowSubs;
398
+ return [...windowSubs, cacheEvictionSub(id, config.evictEveryMs)];
399
+ }
400
+ function subscribers() {
401
+ return { deadline: subscribeBatchWindow, cache: cacheEvictionSubscribe };
402
+ }
403
+ function handlers() {
404
+ return {
405
+ resilient_run: (cmd) => {
406
+ const request = cmd.input;
407
+ const ask = createJevAsk({
408
+ questions: request.questions,
409
+ ...config.port === void 0 ? {} : { port: config.port },
410
+ ...config.fallback === void 0 ? {} : { fallback: config.fallback },
411
+ ...config.model === void 0 ? {} : { model: config.model }
412
+ });
413
+ return ask.handlers().resilient_run(cmd);
414
+ }
415
+ };
416
+ }
417
+ return {
418
+ init,
419
+ add,
420
+ onWindow,
421
+ onBatchOk,
422
+ onBatchErr,
423
+ onEvict,
424
+ answerFor,
425
+ subs,
426
+ subscribers,
427
+ handlers
428
+ };
429
+ }
430
+
431
+ export { DEFAULT_CLASSIFY_MAX_ITEMS, DEFAULT_JEV_MODEL, JEV_ENDPOINT, JevAskFailure, classifyStatus, createClassifyBatch, createJevAsk, isJevErr, isTransientJevAskErr, jevAskCmdDef, jevQuestions, liftJevAsk, parseAnswers };
432
+ //# sourceMappingURL=index.js.map
433
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/internal/jev/protocol/index.ts","../../src/internal/jev/ask/index.ts","../../src/internal/jev/classify-batch/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @packageDocumentation\n * internal/jev/protocol — the wire contract of TypeSafe **Jev** (System One)\n * as types plus two pure functions, and nothing that performs I/O. Internal\n * since #216 — not published on any subpath; the `ask` child that opens the\n * socket imports it from here.\n *\n * The contract is transcribed from `https://docs.typesafe.ai/api`, re-verified\n * 2026-09-21: `POST https://api.typesafe.ai/v1/systemone`, `Authorization:\n * Bearer <API_KEY>`, request `{ state, model, questions }`, response\n * `{ model, answers, usage }`. Where this module and that page disagree, the\n * page is right and this module is a bug.\n *\n * ## What this module is for\n *\n * A Jev call is a map of questions you name, and an answer comes back under\n * each name. That is a shape TypeScript can hold onto, and the whole point of\n * typing it here is that a **choice** question's `criteria` keys ARE its\n * answer's `choice` domain — write the rubric once and the narrowing is free\n * at the call site:\n *\n * ```ts\n * const qs = jevQuestions({\n * category: {\n * type: \"choice\",\n * instructions: \"Which budget line is this?\",\n * criteria: { groceries: \"Supermarkets\", dining: \"Restaurants\" },\n * },\n * });\n * // parsed.answers.category.choice : \"groceries\" | \"dining\"\n * ```\n *\n * `jevQuestions` is an identity function with a `const` type parameter; it\n * exists so the literal keys survive inference without every call site\n * spelling `as const`. `JevAnswers<Q>` is the mapped type that turns such a\n * questions map into its answers map.\n *\n * ## Why parsing is a pure function returning data\n *\n * `parseAnswers` never throws — a response that disagrees with the questions\n * that produced it is a recoverable failure with an obvious next move (retry,\n * re-prompt, give up on this one item), so it is DATA: a closed `JevErr`\n * union of `{ _tag }` values that survives a JSON round-trip into Model\n * (ADR 0011). The type-level guarantee above is a *claim about the wire*, and\n * `parseAnswers` is the one place that claim is checked against a body the\n * network actually produced. Every `unknown` reaches a `JevErr`; nothing\n * reaches a `throw`.\n *\n * Both halves of a choice question's claim are checked, because both are cast\n * away at the tail of `parseAnswers`: `choice` must be one of the criteria\n * keys, and `probabilities` must be keyed by EXACTLY those keys — none\n * missing, none extra. A partial distribution typed `Record<K, number>` is the\n * representable-invalid state this module exists to refuse, and it arrives\n * through this gate or not at all.\n *\n * ## Why status classification lives here and not in `ask`\n *\n * \"429 and 529 back off, everything else non-2xx is terminal\" is a fact about\n * the protocol, published in the same reference page as the body shapes, and\n * `ask` re-deriving it is how the retry policy and the wire contract drift\n * apart. `classifyStatus` is the single reading.\n *\n * ## Bounds the API enforces and this module does not\n *\n * A Choice takes at most 255 options and a Score takes at most 10 levels.\n * `JevScoreQuestion` encodes the *lower* bound — a Score with fewer than two\n * levels does not compile — because a two-element minimum is a tuple, which\n * costs nothing. The upper bounds are not encoded: spelling them as a union\n * of nine tuple arities (or 255 of them) buys a compile error in place of a\n * `422`, at the price of unreadable diagnostics on every ordinary Score. They\n * are the API's `422`, which `classifyStatus` already calls terminal.\n */\n\n// ── the shared instruction / description slot ──────────────────────────────\n\n/**\n * What every `instructions` and every criterion description accepts.\n *\n * The reference page allows a string, an object, or an array in all three\n * slots: a long question carrying data it refers to is written as an object\n * with the question in one field and the data in the others. Typing it as\n * `string` alone would reject the documented structured form.\n */\nexport type JevText =\n | string\n | Readonly<Record<string, unknown>>\n | readonly unknown[];\n\n// ── questions ──────────────────────────────────────────────────────────────\n\n/** The three question types, as the `type` discriminant spells them. */\nexport type JevQuestionType = \"choice\" | \"score\" | \"noul\";\n\n/**\n * A choice question's rubric: option key → description, or `null` where an\n * option needs no extra detail. The keys are the answer's `choice` domain.\n */\nexport type JevChoiceCriteria = Readonly<Record<string, JevText | null>>;\n\n/** Pick one option from a set you define. */\nexport interface JevChoiceQuestion<\n C extends JevChoiceCriteria = JevChoiceCriteria,\n> {\n readonly type: \"choice\";\n readonly instructions: JevText;\n readonly criteria: C;\n}\n\n/**\n * A score question's rubric: an ORDERED list of level descriptions, at least\n * two of them. The API accepts up to ten.\n */\nexport type JevScoreCriteria = readonly [JevText, JevText, ...JevText[]];\n\n/** Rate the state along an ordered rubric. */\nexport interface JevScoreQuestion {\n readonly type: \"score\";\n readonly instructions: JevText;\n readonly criteria: JevScoreCriteria;\n}\n\n/** A yes/no question. `criteria` is optional; both arms are required when it is present. */\nexport interface JevNoulQuestion {\n readonly type: \"noul\";\n readonly instructions: JevText;\n readonly criteria?: {\n readonly true: JevText;\n readonly false: JevText;\n };\n}\n\n/** One typed question. */\nexport type JevQuestion =\n | JevChoiceQuestion\n | JevScoreQuestion\n | JevNoulQuestion;\n\n/** The `questions` map: an id you choose → the question asked under it. */\nexport type JevQuestionMap = Readonly<Record<string, JevQuestion>>;\n\n/**\n * Identity, with the literal keys kept.\n *\n * The `const` type parameter is the whole function: it preserves each choice\n * question's `criteria` keys as literals, so `JevAnswers<typeof qs>` can name\n * them. Without it the inferred type is `Record<string, string>` and the\n * narrowing this module exists for is gone before `parseAnswers` is reached.\n */\nexport const jevQuestions = <const Q extends JevQuestionMap>(questions: Q): Q =>\n questions;\n\n// ── the request ────────────────────────────────────────────────────────────\n\n/** The evaluation endpoint. */\nexport const JEV_ENDPOINT = \"https://api.typesafe.ai/v1/systemone\" as const;\n\n/** The content to evaluate: text, or structured data. */\nexport type JevState =\n | string\n | Readonly<Record<string, unknown>>\n | readonly unknown[];\n\n/** The request body of `POST /v1/systemone`. */\nexport interface JevRequest<Q extends JevQuestionMap = JevQuestionMap> {\n readonly state: JevState;\n readonly model: string;\n readonly questions: Q;\n}\n\n// ── answers ────────────────────────────────────────────────────────────────\n\n/** The yes/no answer, on a scale from 0 (no) to 1 (yes). */\nexport interface JevNoulAnswer {\n readonly type: \"noul\";\n readonly noul: number;\n}\n\n/**\n * The chosen option and the full distribution over the options.\n *\n * `K` is the choice question's own criteria keys, which is why `choice` is a\n * union rather than a `string` and `probabilities` is total over the options.\n */\nexport interface JevChoiceAnswer<K extends string = string> {\n readonly type: \"choice\";\n readonly choice: K;\n readonly probabilities: Readonly<Record<K, number>>;\n readonly confidence: number;\n}\n\n/**\n * The probability-weighted value across the levels — it can land BETWEEN\n * levels, which is why `score` is a `number` and not an index. `legend` and\n * `probabilities` are keyed by the level index as a string.\n */\nexport interface JevScoreAnswer {\n readonly type: \"score\";\n readonly score: number;\n readonly legend: Readonly<Record<string, string>>;\n readonly probabilities: Readonly<Record<string, number>>;\n readonly confidence: number;\n}\n\n/** One typed answer. */\nexport type JevAnswer = JevChoiceAnswer | JevScoreAnswer | JevNoulAnswer;\n\n/** The answer a given question type yields, with the choice union carried through. */\nexport type JevAnswerFor<Q> = Q extends {\n readonly type: \"choice\";\n readonly criteria: infer C;\n}\n ? JevChoiceAnswer<Extract<keyof C, string>>\n : Q extends { readonly type: \"score\" }\n ? JevScoreAnswer\n : Q extends { readonly type: \"noul\" }\n ? JevNoulAnswer\n : never;\n\n/** A questions map turned into its answers map, id for id. */\nexport type JevAnswers<Q extends JevQuestionMap> = {\n readonly [K in keyof Q]: JevAnswerFor<Q[K]>;\n};\n\n/** Token usage for the request. */\nexport interface JevUsage {\n readonly input_tokens: number;\n readonly output_tokens: number;\n}\n\n/** The response body of `POST /v1/systemone`. */\nexport interface JevResponse<Q extends JevQuestionMap = JevQuestionMap> {\n readonly model: string;\n readonly answers: JevAnswers<Q>;\n readonly usage: JevUsage;\n}\n\n// ── failures are data ──────────────────────────────────────────────────────\n\n/**\n * Every way a response can fail to be the answers to the questions asked.\n *\n * Closed, `{ _tag }`-discriminated, JSON-round-trippable: a consumer folds one\n * of these into Model and routes on `_tag` (ADR 0011). `path` and `id` say\n * WHERE, so a failure names the question it is about rather than the whole\n * call.\n */\nexport type JevErr =\n /** The envelope is not a Jev response at all — not an object, or `model` /\n * `answers` / `usage` missing or of the wrong shape. */\n | { readonly _tag: \"malformed_body\"; readonly reason: string }\n /** A question id in the request has no answer under it in the response. */\n | { readonly _tag: \"missing_answer\"; readonly id: string }\n /** An answer arrived, but its `type` is not its question's. */\n | {\n readonly _tag: \"answer_type_mismatch\";\n readonly id: string;\n readonly expected: JevQuestionType;\n readonly received: string;\n }\n /** A choice answer picked something that is not one of its criteria keys. */\n | {\n readonly _tag: \"off_criteria_choice\";\n readonly id: string;\n readonly choice: string;\n readonly options: readonly string[];\n }\n /** A choice answer's `probabilities` keys are not exactly its question's\n * criteria keys. `JevChoiceAnswer<K>` types that map as TOTAL over `K`, so\n * a partial or off-criteria one is the representable-invalid state this\n * module exists to refuse. `missing` and `extra` say which way it failed. */\n | {\n readonly _tag: \"off_criteria_probabilities\";\n readonly id: string;\n readonly missing: readonly string[];\n readonly extra: readonly string[];\n readonly options: readonly string[];\n }\n /** The answer's `type` is right and its payload is not — a missing\n * `confidence`, a `probabilities` that is not a number map, and so on. */\n | {\n readonly _tag: \"malformed_answer\";\n readonly id: string;\n readonly reason: string;\n };\n\n/**\n * The tags {@link JevErr} is closed over, witnessed against the union.\n *\n * The `satisfies` is the point: it is the compiler checking this record's keys\n * against `JevErr[\"_tag\"]` in BOTH directions — a union arm with no entry here\n * fails totality, and an entry naming no arm fails the excess-property check\n * on the literal. Before it, the set was `ReadonlySet<string>` and a new arm\n * was tied to its runtime guard by reviewer attention alone: omit the entry\n * and {@link isJevErr} silently answers `false` for that arm forever.\n */\nconst JEV_ERR_TAG_WITNESS = {\n malformed_body: true,\n missing_answer: true,\n answer_type_mismatch: true,\n off_criteria_choice: true,\n off_criteria_probabilities: true,\n malformed_answer: true,\n} as const satisfies Record<JevErr[\"_tag\"], true>;\n\n/**\n * The membership set {@link isJevErr} tests against — the single reading of\n * the union's tags, so nothing downstream re-derives it from a `\"_tag\" in x`\n * test.\n */\nconst JEV_ERR_TAGS: ReadonlySet<JevErr[\"_tag\"]> = new Set(\n Object.keys(JEV_ERR_TAG_WITNESS) as readonly JevErr[\"_tag\"][],\n);\n\n/**\n * Is `value` a {@link JevErr}?\n *\n * The discriminant is the `_tag` VALUE against the closed set above, never the\n * bare presence of the key. A `JevAnswers` map is keyed by the caller's own\n * question ids, so a caller may legally name a question `_tag` — and then\n * `\"_tag\" in answers` is `true`. The value under it is an ANSWER, which is\n * always an object and never one of these string literals, so reading the\n * value is the one test a caller's id space cannot reach.\n */\nexport function isJevErr(value: object): value is JevErr {\n if (!(\"_tag\" in value)) return false;\n const tag: unknown = (value as { readonly _tag: unknown })._tag;\n // The set is keyed over the union's tags, and the question being asked is\n // whether an arbitrary string is one of them — a read-only widening, sound\n // because `has` only ever reads.\n const tags: ReadonlySet<string> = JEV_ERR_TAGS;\n return typeof tag === \"string\" && tags.has(tag);\n}\n\n/** What `parseAnswers` returns: typed answers, or one `JevErr`. Never a throw. */\nexport type JevParse<Q extends JevQuestionMap> =\n | {\n readonly ok: true;\n readonly answers: JevAnswers<Q>;\n readonly model: string;\n readonly usage: JevUsage;\n }\n | { readonly ok: false; readonly error: JevErr };\n\n// ── parsing ────────────────────────────────────────────────────────────────\n\ntype Obj = Readonly<Record<string, unknown>>;\n\nconst isObj = (v: unknown): v is Obj =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\nconst isNum = (v: unknown): v is number =>\n typeof v === \"number\" && Number.isFinite(v);\n\n/** Every value of `v` is a finite number. `v` itself must already be an object. */\nconst isNumMap = (v: unknown): v is Readonly<Record<string, number>> =>\n isObj(v) && Object.values(v).every(isNum);\n\nconst isStrMap = (v: unknown): v is Readonly<Record<string, string>> =>\n isObj(v) && Object.values(v).every((x) => typeof x === \"string\");\n\nconst err = (\n error: JevErr,\n): { readonly ok: false; readonly error: JevErr } => ({\n ok: false,\n error,\n});\n\n/**\n * Check one answer against the question that asked for it.\n *\n * Returns `undefined` on a match — the answer is then structurally the shape\n * `JevAnswerFor<Q>` names, and the cast at the end of `parseAnswers` is that\n * fact rather than a hope. Returning the error instead of throwing keeps the\n * whole walk branch-free of `try`.\n */\nconst checkAnswer = (\n id: string,\n question: JevQuestion,\n answer: unknown,\n): JevErr | undefined => {\n if (!isObj(answer)) {\n return { _tag: \"malformed_answer\", id, reason: \"answer is not an object\" };\n }\n const received = answer[\"type\"];\n if (typeof received !== \"string\") {\n return { _tag: \"malformed_answer\", id, reason: \"answer has no `type`\" };\n }\n if (received !== question.type) {\n return {\n _tag: \"answer_type_mismatch\",\n id,\n expected: question.type,\n received,\n };\n }\n\n if (question.type === \"noul\") {\n return isNum(answer[\"noul\"])\n ? undefined\n : { _tag: \"malformed_answer\", id, reason: \"`noul` is not a number\" };\n }\n\n if (!isNum(answer[\"confidence\"])) {\n return {\n _tag: \"malformed_answer\",\n id,\n reason: \"`confidence` is not a number\",\n };\n }\n const probabilities = answer[\"probabilities\"];\n if (!isNumMap(probabilities)) {\n return {\n _tag: \"malformed_answer\",\n id,\n reason: \"`probabilities` is not a map of numbers\",\n };\n }\n\n if (question.type === \"score\") {\n if (!isNum(answer[\"score\"])) {\n return {\n _tag: \"malformed_answer\",\n id,\n reason: \"`score` is not a number\",\n };\n }\n return isStrMap(answer[\"legend\"])\n ? undefined\n : {\n _tag: \"malformed_answer\",\n id,\n reason: \"`legend` is not a map of strings\",\n };\n }\n\n // choice — the two checks the type-level contract rests on.\n const choice = answer[\"choice\"];\n if (typeof choice !== \"string\") {\n return { _tag: \"malformed_answer\", id, reason: \"`choice` is not a string\" };\n }\n const options = Object.keys(question.criteria);\n if (!options.includes(choice)) {\n return { _tag: \"off_criteria_choice\", id, choice, options };\n }\n\n // `JevChoiceAnswer<K>` says `probabilities` is TOTAL over the criteria keys\n // and carries nothing else. A `Record<K, number>` the bytes under-fill is\n // exactly the value the cast at the tail of `parseAnswers` would otherwise\n // launder into the caller's hands.\n const missing = options.filter((k) => !Object.hasOwn(probabilities, k));\n const extra = Object.keys(probabilities).filter((k) => !options.includes(k));\n return missing.length === 0 && extra.length === 0\n ? undefined\n : { _tag: \"off_criteria_probabilities\", id, missing, extra, options };\n};\n\n/**\n * Turn an `unknown` response body into the typed answers for `questions`, or\n * into one `JevErr`. Pure, total, and never throwing on any input.\n *\n * The walk is question-driven, not body-driven: every id the request asked\n * about must be answered, and each answer is checked against ITS question's\n * type and — for a choice — against that question's own criteria keys, both as\n * the `choice` picked and as the exact key set of `probabilities`. An\n * answer under an id nobody asked about is ignored rather than refused; the\n * questions are the contract, and a wider response still satisfies it.\n */\nexport const parseAnswers = <Q extends JevQuestionMap>(\n questions: Q,\n body: unknown,\n): JevParse<Q> => {\n if (!isObj(body))\n return err({ _tag: \"malformed_body\", reason: \"body is not an object\" });\n\n const model = body[\"model\"];\n if (typeof model !== \"string\") {\n return err({ _tag: \"malformed_body\", reason: \"`model` is not a string\" });\n }\n\n const usage = body[\"usage\"];\n if (\n !isObj(usage) ||\n !isNum(usage[\"input_tokens\"]) ||\n !isNum(usage[\"output_tokens\"])\n ) {\n return err({\n _tag: \"malformed_body\",\n reason: \"`usage` is not `{ input_tokens, output_tokens }`\",\n });\n }\n\n const answers = body[\"answers\"];\n if (!isObj(answers)) {\n return err({\n _tag: \"malformed_body\",\n reason: \"`answers` is not an object\",\n });\n }\n\n for (const [id, question] of Object.entries(questions)) {\n if (!Object.hasOwn(answers, id)) {\n return err({ _tag: \"missing_answer\", id });\n }\n const bad = checkAnswer(id, question, answers[id]);\n if (bad !== undefined) return err(bad);\n }\n\n return {\n ok: true,\n // Every id of `questions` passed `checkAnswer`, which is exactly the set of\n // obligations `JevAnswers<Q>` states. `unknown` is the bridge because the\n // per-id narrowing happened in a loop, where the compiler cannot carry it.\n answers: answers as unknown as JevAnswers<Q>,\n model,\n usage: {\n input_tokens: usage[\"input_tokens\"],\n output_tokens: usage[\"output_tokens\"],\n },\n };\n};\n\n// ── status classification ──────────────────────────────────────────────────\n\n/**\n * What a caller does next with an HTTP status.\n *\n * `retry` means back off and send it again; `terminal` means this request will\n * never succeed as written. `ok` is the 2xx arm — naming it keeps the function\n * total, so `ask` switches on three cases instead of testing 2xx itself and\n * then asking here.\n */\nexport type JevHttpStatus = \"ok\" | \"retry\" | \"terminal\";\n\n/**\n * Classify one HTTP status, per the reference page's error table.\n *\n * 429 (rate limited) and 529 (overloaded) are the two the page tells you to\n * back off on. 401 (bad key) and 422 (the body failed validation) will fail\n * identically forever. Every other non-2xx is terminal by default: an\n * unrecognized failure is not evidence that retrying helps, and a retry loop\n * over one is the expensive way to find that out.\n */\nexport const classifyStatus = (status: number): JevHttpStatus => {\n if (status >= 200 && status < 300) return \"ok\";\n if (status === 429 || status === 529) return \"retry\";\n return \"terminal\";\n};\n","/**\n * @packageDocumentation\n * internal/jev/ask — one Cmd that asks Jev a question map, over\n * `../../resilience/resilient-call`, with the HTTP caller injected as a port\n * and a pure fallback behind it. Internal since #217 — not published on any\n * subpath; `../protocol` is the wire contract it speaks.\n *\n * This is `../../llm-call` for Jev: a config object, the resilient-call slice\n * it INHERITS, and one interpret handler that calls the port, classifies the\n * status, parses the body against the questions that produced it, and returns\n * the enriched resilient settle Msg so it re-enters the host reducer.\n * `init`, `attempt`, `succeed`, `onTimer` and `subs` are resilient-call's verbs\n * forwarded; there is no retry loop, no timer and no `Date.now()` in any verb\n * here.\n *\n * ## The two ports and the one policy\n *\n * - `port: JevPort<Q>` — the injected HTTP caller,\n * `(request, signal?) => Promise<{ status, body }>`. A `fetch`-backed\n * adapter and a scripted test fake satisfy it identically, and the door\n * never reads an env var or holds a key: whoever builds the adapter owns\n * the `Authorization` header. `undefined` is the no-key case, and it is a\n * legal configuration — see the fallback.\n * - `fallback?: (request) => JevAnswers<Q> | JevErr` — a PURE deterministic\n * decider. It answers on the two paths where the network cannot: `port` is\n * absent, or the resilient retry budget is spent. Pure is the requirement,\n * not a preference — the exhaustion path calls it inside the `fail` verb,\n * so a fallback that read a clock or a socket would break replay.\n * - `retry: RetryPolicy` — handed straight to resilient-call. Omit it and the\n * first transient failure is terminal, exactly as resilient-call documents.\n *\n * ## Which failures back off and which do not\n *\n * `classifyStatus` (the protocol child, the single reading of the error table)\n * splits the answer three ways, and that split IS the retry decision:\n *\n * - `ok` → parse. A body that disagrees with the questions asked settles\n * `resilient_err` carrying the protocol's own {@link JevErr} — terminal,\n * because the same request will produce the same body.\n * - `retry` (429 / 529) → a TRANSIENT {@link JevAskErr}. `fail` feeds it to\n * resilient-call's backoff, so the call waits and re-issues.\n * - `terminal` (401 / 422 / anything else non-2xx) → a terminal\n * {@link JevAskErr}. `fail` settles it through `settleFailed`: the call\n * ends now, the breaker is not tripped and the port is NOT called again.\n *\n * ## Typical wiring\n *\n * const ask = createJevAsk({\n * questions, // the map; its keys type the answers\n * port: fetchJevPort(apiKey), // or omit it and configure `fallback`\n * fallback: (req) => offlineGuess(req),\n * retry: defaultRetryPolicy,\n * });\n *\n * // in the machine:\n * init: () => [{ resilience: ask.init() }, []],\n * update: {\n * ask_jev: (s, m) => liftJevAsk(s, ask.attempt(s.resilience, m.key, m.state, m.at)),\n * // `resilient_ok` / `resilient_err` RE-ENTER from `handlers` (the settle\n * // Msg the interpret handler returns). Run the inherited verb FIRST so the\n * // backoff loop advances, THEN fold `m.result` / `m.error` into the host's\n * // own state — the enrichment belongs in the reducer arm, not the handler.\n * resilient_ok: (s, m) => {\n * const [slice, cmds] = ask.succeed(s.resilience, m.key, m);\n * return [{ ...s, resilience: slice, answers: m.result.answers }, cmds];\n * },\n * resilient_err: (s, m) => {\n * const [slice, cmds] = ask.fail(s.resilience, m.key, m);\n * return [{ ...s, resilience: slice, failure: m.error }, cmds];\n * },\n * deadline_exceeded: (s, m) => liftJevAsk(s, ask.onTimer(s.resilience, m)),\n * },\n * subscriptions: (s) => ask.subs(s.resilience),\n * subscribe: { deadline: subscribeDeadline },\n * interpret: ask.handlers(),\n */\n\nimport { describeError } from \"../../../describe-error\";\nimport type { Cmd } from \"../../../index\";\nimport { MsgType } from \"../../../protocol\";\nimport type { RetryPolicy } from \"../../../retry-backoff\";\nimport {\n createResilientCall,\n type DeadlineExceeded,\n type DeadlineSub,\n deadlineSub,\n type FailMsg,\n liftResilience,\n type ResilientConfig,\n type ResilientState,\n type RunCmd,\n runCmdDef,\n type SucceedMsg,\n subscribeDeadline,\n} from \"../../resilience/resilient-call\";\nimport {\n classifyStatus,\n isJevErr,\n type JevAnswers,\n type JevErr,\n type JevQuestionMap,\n type JevRequest,\n type JevState,\n type JevUsage,\n parseAnswers,\n} from \"../protocol\";\n\n// ===========================================================================\n// The DI ports.\n// ===========================================================================\n\n/**\n * The injected HTTP caller — the one seam that touches the network.\n *\n * It returns the status and the undecoded body rather than throwing on a\n * non-2xx, because WHICH non-2xx it is decides whether the call backs off, and\n * a thrown adapter error has already lost that. `signal` is optional so a\n * `fetch` adapter can be cancelled; resilient-call issues no signal today, and\n * the slot exists so an adapter's own shape does not have to change when it\n * does.\n *\n * A `fetch` adapter and a scripted test fake satisfy this identically, which is\n * the whole reason the key lives in the adapter's closure and never in config.\n */\nexport type JevPort<Q extends JevQuestionMap = JevQuestionMap> = (\n request: JevRequest<Q>,\n signal?: AbortSignal,\n) => Promise<{ readonly status: number; readonly body: unknown }>;\n\n/**\n * The pure decider that answers when the network cannot.\n *\n * Called on exactly two paths: `port` is absent (the no-key case), and the\n * resilient retry budget is spent. It must be a pure function of the request —\n * the exhaustion path runs it inside the `fail` VERB, which replay re-runs, so\n * a clock read or an I/O call here would make the machine unreplayable.\n * Returning a {@link JevErr} is how a fallback says \"I have no answer for\n * this one\"; the call then settles as that error.\n */\nexport type JevFallback<Q extends JevQuestionMap> = (\n request: JevRequest<Q>,\n) => JevAnswers<Q> | JevErr;\n\n// ===========================================================================\n// Failures — the protocol's, plus the three this door adds.\n// ===========================================================================\n\n/**\n * Every way an ask can fail, as DATA.\n *\n * A superset of the protocol child's {@link JevErr}: a parse failure is\n * reported with the protocol's own tag untouched, and the three tags below are\n * the ones only a caller can observe. `{_tag}`-discriminated and\n * JSON-round-trippable like the rest (ADR 0011), because it is carried on the\n * settle Msg and stored in the slice's `failed` phase.\n *\n * `http_retry` and `port_threw` are the TRANSIENT pair — {@link isTransientJevAskErr}\n * is the single reading, and `fail` backs off on exactly those two.\n */\nexport type JevAskErr =\n | JevErr\n /** 429 / 529 — the statuses `classifyStatus` says to back off on. */\n | { readonly _tag: \"http_retry\"; readonly status: number }\n /** 401 / 422 / any other non-2xx — this request fails identically forever. */\n | { readonly _tag: \"http_terminal\"; readonly status: number }\n /** The port itself rejected (a socket error, a DNS failure) — transient. */\n | { readonly _tag: \"port_threw\"; readonly reason: string }\n /** No `port` and no `fallback`: the knob was configured with no way to answer. */\n | { readonly _tag: \"no_answer_path\" };\n\n/**\n * Does this failure deserve another attempt?\n *\n * The one place the transient/terminal split is read. A rate limit and a dropped\n * socket are the two failures a second attempt can clear; a 401, a 422 and every\n * parse failure will reproduce exactly, so retrying one spends a real HTTP call\n * to learn nothing.\n */\nexport function isTransientJevAskErr(error: JevAskErr): boolean {\n return error._tag === \"http_retry\" || error._tag === \"port_threw\";\n}\n\n/**\n * The carrier that gets a {@link JevAskErr} out of the port and through\n * resilient-call's throw seam intact.\n *\n * resilient-call routes a rejected port to a failure Msg carrying the raw\n * thrown value, so throwing is the only way the handler can say \"this attempt\n * failed\" — and a bare `Error` would arrive with its classification already\n * lost. The typed payload rides on `jev`; the slice never stores this object\n * (the verbs store `jev` itself), so nothing un-serializable reaches Model.\n */\nexport class JevAskFailure extends Error {\n constructor(readonly jev: JevAskErr) {\n super(`jev ask: ${jev._tag}`);\n this.name = \"JevAskFailure\";\n }\n}\n\n/** Read any thrown value back as a {@link JevAskErr}. A foreign throw is transient. */\nfunction toAskErr(error: unknown): JevAskErr {\n if (error instanceof JevAskFailure) return error.jev;\n return { _tag: \"port_threw\", reason: describeError(error) };\n}\n\n// ===========================================================================\n// Config, request and result.\n// ===========================================================================\n\n/** The model the door asks for when config names none. */\nexport const DEFAULT_JEV_MODEL = \"jev-latest\";\n\n/** No tokens were spent — what a fallback answer's usage is. */\nconst NO_USAGE: JevUsage = { input_tokens: 0, output_tokens: 0 };\n\n/**\n * The jev-ask knob. `questions` is the load-bearing one: it is both the map\n * sent on every request and the type that makes the answers narrow at the call\n * site, so it belongs to the knob rather than to a call.\n */\nexport interface JevAskConfig<Q extends JevQuestionMap> {\n /** The question map every request carries; its keys type the answers. */\n readonly questions: Q;\n /** DI port — the HTTP caller. Absent = the no-key case; `fallback` answers instead. */\n readonly port?: JevPort<Q>;\n /** The pure decider for the no-port and budget-spent paths. Absent → those settle as an error. */\n readonly fallback?: JevFallback<Q>;\n /** Backoff policy, composed into `../../resilience/resilient-call`. Omit → no backoff. */\n readonly retry?: RetryPolicy;\n /** The model id asked for. Defaults to {@link DEFAULT_JEV_MODEL}. */\n readonly model?: string;\n}\n\n/**\n * The settled answer carried on `resilient_ok`.\n *\n * `source` is not decoration: a fallback answer and a model answer are both\n * valid answers with identical shape, and a host that routes on confidence — or\n * bills on usage — has to be able to tell them apart. A fallback's `usage` is\n * zero because nothing was spent.\n */\nexport interface JevOk<Q extends JevQuestionMap> {\n /** The typed answers, one per question id. */\n readonly answers: JevAnswers<Q>;\n /** The model that answered, as the response reported it (or the requested one, for a fallback). */\n readonly model: string;\n /** Tokens spent. Zero on the fallback path. */\n readonly usage: JevUsage;\n /** Which path produced this answer. */\n readonly source: \"port\" | \"fallback\";\n}\n\n// ===========================================================================\n// The Cmd + Msgs the knob speaks.\n// ===========================================================================\n\n/**\n * The one effect this knob emits: run the ask for `key` with the plain-data\n * {@link JevRequest} (ADR 0014 — a Cmd is DECLARED, so its input, ok and err\n * channels are types on the constructor rather than a convention). It is\n * resilient-call's `runCmdDef` specialized to this door's input and result, the\n * same way `../../idempotency/idempotent-intake` mints its defs per knob: `Q` is\n * a type parameter, so the def is a factory and not a module constant.\n */\nexport function jevAskCmdDef<Q extends JevQuestionMap>() {\n return runCmdDef<JevRequest<Q>, JevOk<Q>>();\n}\n\n/** The Cmd the verbs emit — `resilient_run` carrying the request. */\nexport type JevAskCmd<Q extends JevQuestionMap> = RunCmd<JevRequest<Q>>;\n\n/** The success settle Msg — resilient-call's, with `result` narrowed to {@link JevOk}. */\nexport type JevSucceedMsg<Q extends JevQuestionMap> = SucceedMsg<JevOk<Q>>;\n\n/** The failure settle Msg — resilient-call's, with `error` narrowed to {@link JevAskErr}. */\nexport type JevFailMsg = Omit<FailMsg, \"error\"> & {\n readonly error: JevAskErr;\n};\n\n/** The retry / deadline timer Msg — `DeadlineExceeded`, inherited. */\nexport type JevTimerMsg = DeadlineExceeded;\n\n// ===========================================================================\n// The knob factory.\n// ===========================================================================\n\n/**\n * Build a jev-ask knob from `config`. `rng` is injected for the inherited retry\n * jitter (pass a fixed `() => 0` in tests to pin backoff; defaults to\n * `Math.random`, read only at resilient-call's verb boundary).\n *\n * The slice and five of the six verbs are resilient-call's, forwarded. `fail` is\n * the one composed verb — it reads the {@link JevAskErr} the handler typed and\n * routes on it (see its docblock); it reimplements no backoff. `handlers` is the\n * new piece: the port call, the status classification, the parse, and the\n * enriched settle Msg.\n */\nexport function createJevAsk<Q extends JevQuestionMap>(\n config: JevAskConfig<Q>,\n rng: () => number = Math.random,\n) {\n const resilientConfig: ResilientConfig = {\n ...(config.retry === undefined ? {} : { retry: config.retry }),\n };\n const rc = createResilientCall<JevRequest<Q>, JevOk<Q>>(resilientConfig, rng);\n const model = config.model ?? DEFAULT_JEV_MODEL;\n\n /** The slice this knob owns — resilient-call's slice verbatim. */\n type State = ResilientState<JevRequest<Q>, JevOk<Q>>;\n\n /**\n * A fallback's answer or its refusal.\n *\n * The discriminant is the protocol child's own {@link isJevErr} — the `_tag`\n * VALUE read against the closed `JevErr` tag set. Testing for the KEY instead\n * reads a caller's question ids as a discriminant they never agreed to: a\n * question legally named `_tag` makes `\"_tag\" in decided` true on a perfectly\n * good answers map, and the successful fallback then settles as a refusal\n * carrying the answers map as its error. An answer is always an object and\n * never one of those five tag literals, so the value test cannot collide.\n */\n function isErrDecision(decided: JevAnswers<Q> | JevErr): decided is JevErr {\n return isJevErr(decided);\n }\n\n /** The request a call under `key` is live with, or `undefined` if it is not live. */\n function liveRequest(s: State, key: string): JevRequest<Q> | undefined {\n const call = s.calls[key];\n if (call?.phase === \"running\" || call?.phase === \"waiting_retry\") {\n return call.input;\n }\n return undefined;\n }\n\n /** The starting slice — resilient-call's. */\n function init(): State {\n return rc.init();\n }\n\n /**\n * Ask the configured questions about `content` under `key`. PURE — it builds\n * the plain-data request (no closures: `state`, `model` and `questions` are\n * all values) and delegates straight to resilient-call's gate.\n */\n function attempt(\n s: State,\n key: string,\n content: JevState,\n at: number,\n ): readonly [State, readonly JevAskCmd<Q>[]] {\n const request: JevRequest<Q> = {\n state: content,\n model,\n questions: config.questions,\n };\n return rc.attempt(s, key, request, at);\n }\n\n /** Record a settled answer for `key`. PURE — resilient-call's `succeed`. */\n function succeed(\n s: State,\n key: string,\n msg: JevSucceedMsg<Q>,\n ): readonly [State, readonly JevAskCmd<Q>[]] {\n return rc.succeed(s, key, msg);\n }\n\n /**\n * Settle `key` from the fallback, as if the fallback's answer were the\n * response. PURE — the fallback is a pure decider, and `succeed` / `settleFailed`\n * are resilient-call's own settle verbs. `s` is the state BEFORE the failing\n * attempt was recorded, so the call is still live and `succeed` closes it\n * normally.\n */\n function settleFromFallback(\n s: State,\n key: string,\n request: JevRequest<Q>,\n fallback: JevFallback<Q>,\n at: number,\n ): readonly [State, readonly JevAskCmd<Q>[]] {\n const decided = fallback(request);\n if (isErrDecision(decided)) return rc.settleFailed(s, key, decided);\n return rc.succeed(s, key, {\n type: MsgType.ResilientOk,\n key,\n result: {\n answers: decided,\n model: request.model,\n usage: NO_USAGE,\n source: \"fallback\",\n },\n at,\n });\n }\n\n /**\n * Record a failure for `key`. PURE. The backoff itself is resilient-call's —\n * nothing here recomputes a delay, counts an attempt or reads a clock. What\n * this verb adds is the routing the typed error makes possible, and it is two\n * decisions:\n *\n * 1. A TERMINAL error settles through `settleFailed`, which ends the call\n * without touching the breaker or the retry counter. Handing a 401 or a\n * parse failure to `fail` instead would re-issue the identical request\n * and trip a breaker over a backend that is perfectly healthy.\n * 2. When the transient path EXHAUSTS the retry budget and a `fallback` is\n * configured, the fallback answers instead of the call settling failed.\n * This is the one place that can be observed — exhaustion is a fact of\n * the slice, not of the handler, so the handler cannot know it is on the\n * last attempt.\n */\n function fail(\n s: State,\n key: string,\n msg: JevFailMsg,\n ): readonly [State, readonly JevAskCmd<Q>[]] {\n if (!isTransientJevAskErr(msg.error)) {\n return rc.settleFailed(s, key, msg.error);\n }\n const request = liveRequest(s, key);\n const settled = rc.fail(s, key, msg);\n const backedOff = settled[0].calls[key]?.phase !== \"failed\";\n if (backedOff || config.fallback === undefined || request === undefined) {\n return settled;\n }\n return settleFromFallback(s, key, request, config.fallback, msg.at);\n }\n\n /** A retry / deadline timer fired. PURE — resilient-call's `onTimer`. */\n function onTimer(\n s: State,\n msg: JevTimerMsg,\n ): readonly [State, readonly JevAskCmd<Q>[]] {\n return rc.onTimer(s, msg);\n }\n\n /** Pre-wired subs — resilient-call's retry-timer subscriptions. */\n function subs(s: State): readonly DeadlineSub[] {\n return rc.subs(s);\n }\n\n // ---- The port the resilient handler drives -----------------------------\n\n /**\n * Run ONE ask: call the port, classify the status, parse the body against the\n * questions that produced it. Resolves to the typed {@link JevOk}; throws a\n * {@link JevAskFailure} on every failure, because throwing is how\n * resilient-call is told an attempt failed. `fail` reads the carried\n * {@link JevAskErr} back and decides whether the throw was worth retrying.\n *\n * With no `port` this is the fallback's whole story: no HTTP call is made, and\n * with no fallback either the knob says so as `no_answer_path` rather than\n * pretending a network failure.\n */\n async function ask(\n request: JevRequest<Q>,\n signal?: AbortSignal,\n ): Promise<JevOk<Q>> {\n if (config.port === undefined) {\n if (config.fallback === undefined) {\n throw new JevAskFailure({ _tag: \"no_answer_path\" });\n }\n const decided = config.fallback(request);\n if (isErrDecision(decided)) throw new JevAskFailure(decided);\n return {\n answers: decided,\n model: request.model,\n usage: NO_USAGE,\n source: \"fallback\",\n };\n }\n\n const { status, body } = await config.port(request, signal);\n const kind = classifyStatus(status);\n if (kind === \"retry\")\n throw new JevAskFailure({ _tag: \"http_retry\", status });\n if (kind === \"terminal\") {\n throw new JevAskFailure({ _tag: \"http_terminal\", status });\n }\n\n const parsed = parseAnswers(config.questions, body);\n if (!parsed.ok) throw new JevAskFailure(parsed.error);\n return {\n answers: parsed.answers,\n model: parsed.model,\n usage: parsed.usage,\n source: \"port\",\n };\n }\n\n // ---- Handlers ----------------------------------------------------------\n\n // resilient-call's `resilient_run` handler over `ask` — the shared\n // Railway-routed invoke (Ok → `resilient_ok`, Err → `resilient_err`), stamped\n // with the one `Date.now()` this module makes, at the effect boundary.\n const resilientRunHandler = rc.handlers({\n run: (request) => ask(request),\n }).resilient_run;\n\n /**\n * Await one invoke and resolve to the ENRICHED settle Msg. The success Msg is\n * resilient-call's as-is (`ask` already returns the typed {@link JevOk}); the\n * failure Msg is its `error: unknown` read back as the typed\n * {@link JevAskErr}, so the host reducer — and `fail` — route on a tag rather\n * than on a stringified throw.\n */\n async function settleOf(\n cmd: JevAskCmd<Q>,\n ): Promise<JevSucceedMsg<Q> | JevFailMsg> {\n const settle = await resilientRunHandler(cmd, {});\n if (settle.type === MsgType.ResilientOk) return settle;\n return {\n type: MsgType.ResilientErr,\n key: settle.key,\n error: toAskErr(settle.error),\n at: settle.at,\n };\n }\n\n /**\n * Pre-wired interpret handler for `resilient_run`. It RETURNS the settle Msg\n * rather than dispatching one: the substrate enqueues an interpret handler's\n * returned Msg as a follow-up onto the dispatch tail, so the host's\n * `resilient_ok` / `resilient_err` arms run `succeed` / `fail` and the\n * inherited backoff loop advances. A handler that dispatched instead would\n * settle one invoke and leave the slice wedged at `running`.\n */\n function handlers(): {\n resilient_run: (\n cmd: JevAskCmd<Q>,\n ) => Promise<JevSucceedMsg<Q> | JevFailMsg>;\n } {\n return { resilient_run: (cmd: JevAskCmd<Q>) => settleOf(cmd) };\n }\n\n return { init, attempt, succeed, fail, onTimer, subs, handlers, ask };\n}\n\n/**\n * The Cmd type a host machine declares in `types.cmd` when it splices a\n * {@link createJevAsk} knob in — {@link JevAskCmd} under the name a `types`\n * block reads well with. It is stated here so a host writes `cmd: {} as\n * JevCmd<Questions>` rather than deriving it from the knob's shape, which is\n * what `ReturnType<Ask[\"attempt\"]>[1][number]` used to be doing at every call\n * site: a spelling of the same type that breaks the moment `attempt`'s tuple\n * changes, and that reads as machinery rather than as a name.\n */\nexport type JevCmd<Q extends JevQuestionMap> = JevAskCmd<Q>;\n\n/**\n * The Sub type a host machine declares in `types.sub` — the deadline Sub\n * `subs` emits, inherited from resilient-call. Named here for the same reason\n * as {@link JevCmd}: a host names the type, it does not re-derive it.\n */\nexport type JevSub = DeadlineSub;\n\n/**\n * Lift a knob result `[slice, cmds]` into a host `[State, cmds]` where the slice\n * lives at `state.resilience` — resilient-call's convenience, re-typed for this\n * door's slice so a consumer wires one import. Pure.\n */\nexport function liftJevAsk<\n S extends { resilience: ResilientState<JevRequest<Q>, JevOk<Q>> },\n Q extends JevQuestionMap,\n C extends Cmd,\n>(\n state: S,\n result: readonly [ResilientState<JevRequest<Q>, JevOk<Q>>, readonly C[]],\n): readonly [S, readonly C[]] {\n return liftResilience(state, result);\n}\n\n/**\n * Re-export the deadline Sub primitives (inherited from resilient-call) so a\n * consumer wires one import: `subscribeDeadline` is the `subscribe` cell,\n * `deadlineSub` builds the Sub literal `subs` emits.\n */\nexport { subscribeDeadline, deadlineSub };\nexport type { DeadlineSub, DeadlineExceeded, ResilientState };\n","/**\n * @packageDocumentation\n * internal/jev/classify-batch — the composition that turns a stream of items\n * into Jev calls. Internal since #218 — not published on any subpath.\n *\n * It writes NO chunker, NO cache, NO concurrency limiter and NO retry. Every\n * one of those already exists as a battery, and this module is the wiring:\n *\n * - `../../flow/batch-window` coalesces `add(item, at)` calls into size- or\n * time-bounded batches (`maxItems`, `maxMs`).\n * - `../../flow/fan-out` bounds how many batches are in flight\n * (`concurrency`), keyed by a batch id that is a pure function of the\n * batch's item keys.\n * - `../../resilience/cache` is the TTL cache keyed by `keyOf(item)`. An item\n * whose key is cached never enters a batch; every settled answer is written\n * back with `ttlMs`.\n * - `../ask` is the one effect: each flushed batch becomes one `resilient_run`\n * Cmd carrying Jev's NATIVE batch form (grill #215, R1.2) — the item array\n * IS the request `state`, and `questions` holds one `choice` question per\n * item, keyed by `keyOf(item)`. There is no `{ transactions }` envelope of\n * any kind.\n *\n * ## The slice is plain data, and time arrives as `at`\n *\n * {@link ClassifyBatchState} is the three batteries' own slices plus a failure\n * map, so it survives a `Store` rehydrate unchanged. Every transition is a Msg\n * through the verbs (`add`, `onWindow`, `onBatchOk`, `onBatchErr`, `onEvict`);\n * no verb reads a clock, and the one `Date.now()` on the path is the one\n * `../ask`'s interpret handler already stamps at the effect boundary.\n *\n * ## What this module deliberately does not decide\n *\n * `answerFor` is a derived READ. It reports `answered` / `failed` / `pending` /\n * `absent` and hands back the choice answer with its own `confidence`; whether\n * a given confidence auto-assigns or goes to triage is the HOST reducer's rule,\n * and putting a threshold here would make one caller's policy everybody's.\n *\n * ## Typical wiring\n *\n * const classify = createClassifyBatch({\n * keyOf: (t) => sanitizedMerchant(t),\n * criteria: { groceries: \"Supermarkets\", dining: \"Restaurants\" },\n * maxItems: 25,\n * maxMs: 2_000,\n * concurrency: 4,\n * ttlMs: 86_400_000,\n * port: fetchJevPort(apiKey),\n * });\n *\n * update: {\n * classify_add: (s, m) => lift(s, classify.add(s.classify, m.item, m.at)),\n * deadline_exceeded: (s, m) => lift(s, classify.onWindow(s.classify, m.atMs)),\n * resilient_ok: (s, m) => lift(s, classify.onBatchOk(s.classify, m)),\n * resilient_err: (s, m) => lift(s, classify.onBatchErr(s.classify, m)),\n * cache_evict: (s, m) => lift(s, classify.onEvict(s.classify, nowFromMsg)),\n * },\n * subscriptions: (s) => classify.subs(s.classify),\n * subscribe: classify.subscribers(),\n * interpret: classify.handlers(),\n */\n\nimport type { Cmd } from \"../../../index\";\nimport {\n type BatchWindow,\n type BatchWindowSub,\n createBatchWindow,\n subscribeBatchWindow,\n} from \"../../flow/batch-window\";\nimport { createFanOut, type FanOutState } from \"../../flow/fan-out\";\nimport {\n type CacheEvictionSub,\n cacheEvictionSub,\n cacheEvictionSubscribe,\n get as cacheGet,\n has as cacheHas,\n set as cacheSet,\n evictExpired,\n initCache,\n type TtlCache,\n} from \"../../resilience/cache\";\nimport {\n createJevAsk,\n DEFAULT_JEV_MODEL,\n type JevAskCmd,\n type JevAskErr,\n type JevFailMsg,\n type JevFallback,\n type JevOk,\n type JevPort,\n type JevSucceedMsg,\n jevAskCmdDef,\n} from \"../ask\";\nimport type {\n JevAnswerFor,\n JevChoiceQuestion,\n JevRequest,\n JevText,\n} from \"../protocol\";\n\n// ===========================================================================\n// The question shape one item gets.\n// ===========================================================================\n\n/**\n * The rubric every item is classified against: option key → description, or\n * `null` where an option needs no extra detail. `C` is the option union, and it\n * is what makes an answer's `choice` narrow at the call site.\n */\nexport type ClassifyCriteria<C extends string> = Readonly<\n Record<C, JevText | null>\n>;\n\n/** The one `choice` question an item is asked. */\nexport type ItemQuestion<C extends string> = JevChoiceQuestion<\n ClassifyCriteria<C>\n>;\n\n/**\n * The `questions` map of one batch: one {@link ItemQuestion} per item, keyed by\n * `keyOf(item)`. This IS Jev's native batch form — the questions map is the\n * fan-out over items, so nothing here wraps the items in an envelope of its own.\n */\nexport type ItemQuestions<C extends string> = Readonly<\n Record<string, ItemQuestion<C>>\n>;\n\n/** The answer one item's question yields. */\nexport type ItemAnswer<C extends string> = JevAnswerFor<ItemQuestion<C>>;\n\n// ===========================================================================\n// Batches, Cmds and Msgs.\n// ===========================================================================\n\n/**\n * One flushed batch, as plain data: the items and the id fan-out addresses it\n * by. `id` is a pure function of the batch's item keys (they are joined with a\n * separator no sanitized key contains), which is what lets a settle Msg — whose\n * `key` is that id — find its batch again after a rehydrate.\n */\nexport interface Batch<I> {\n readonly id: string;\n readonly items: readonly I[];\n}\n\n/** The Cmd a flushed batch becomes — `../ask`'s, carrying the native request. */\nexport type ClassifyBatchCmd<C extends string> = JevAskCmd<ItemQuestions<C>>;\n\n/** The success settle Msg — `../ask`'s, with the batch's answers. */\nexport type ClassifyBatchOkMsg<C extends string> = JevSucceedMsg<\n ItemQuestions<C>\n>;\n\n/** The failure settle Msg — `../ask`'s, with the typed {@link JevAskErr}. */\nexport type ClassifyBatchErrMsg = JevFailMsg;\n\n/**\n * The internal Cmd the batch window flushes into. It never leaves this module:\n * `add` and `onWindow` intercept it and hand the items to fan-out, which is\n * what bounds how many batches are in flight. Letting the window emit the ask\n * Cmd directly would flush straight past `concurrency`.\n */\ntype FlushCmd<I> = Cmd<\"classify_batch_flush\"> & {\n readonly items: readonly I[];\n};\n\n// ===========================================================================\n// Config and slice.\n// ===========================================================================\n\n/** The default page size — the one the grill settled on for Jev. */\nexport const DEFAULT_CLASSIFY_MAX_ITEMS = 25;\n\n/** The knob. Every field is a policy this module refuses to invent. */\nexport interface ClassifyBatchConfig<I, C extends string> {\n /**\n * The cache key and the question id of an item — e.g. a sanitized merchant\n * string, so two transactions at the same shop share one answer. PURE.\n */\n readonly keyOf: (item: I) => string;\n /** The rubric every item is classified against. Its keys are the answer domain. */\n readonly criteria: ClassifyCriteria<C>;\n /**\n * The `instructions` for one item's question. Defaults to a template naming\n * the item's key, which is what tells the model WHICH element of the request\n * `state` the question is about.\n */\n readonly instructions?: (key: string, item: I) => JevText;\n /** Size trigger, forwarded to the batch window. Defaults to {@link DEFAULT_CLASSIFY_MAX_ITEMS}. */\n readonly maxItems?: number;\n /** Latency ceiling in ms, forwarded to the batch window. */\n readonly maxMs: number;\n /** Max batches in flight, forwarded to fan-out. */\n readonly concurrency: number;\n /** How long a settled answer stays cached, forwarded to the TTL cache. */\n readonly ttlMs: number;\n /** Eviction tick for the TTL cache. Omit and no eviction Sub is declared. */\n readonly evictEveryMs?: number;\n /** The model asked for. Forwarded to `../ask`'s default when omitted. */\n readonly model?: string;\n /** DI port — the HTTP caller. Forwarded to `../ask`; absent is the no-key case. */\n readonly port?: JevPort<ItemQuestions<C>>;\n /** The pure decider for the no-port path. Forwarded to `../ask`. */\n readonly fallback?: JevFallback<ItemQuestions<C>>;\n}\n\n/**\n * The slice: the three batteries' own slices, plus the one fact none of them\n * holds — which keys a failed batch left unanswered. All plain data.\n */\nexport interface ClassifyBatchState<I, C extends string> {\n /** The open batch window — `../../flow/batch-window`'s slice. */\n readonly window: BatchWindow<I>;\n /** The in-flight batches — `../../flow/fan-out`'s slice. */\n readonly fanOut: FanOutState<Batch<I>, JevOk<ItemQuestions<C>>>;\n /** The answers, keyed by `keyOf` — `../../resilience/cache`'s slice. */\n readonly cache: TtlCache<ItemAnswer<C>>;\n /** Keys whose batch settled `resilient_err`, with the error that settled it. */\n readonly failed: Readonly<Record<string, JevAskErr>>;\n}\n\n/** What {@link ClassifyBatchKnob.answerFor} reports about one key. */\nexport type KeyAnswer<C extends string> =\n /** Answered and unexpired: the host applies its own confidence rule to this. */\n | { readonly status: \"answered\"; readonly answer: ItemAnswer<C> }\n /** The batch carrying this key settled `resilient_err`. Nothing was cached. */\n | { readonly status: \"failed\"; readonly error: JevAskErr }\n /** Buffered in the open window, or in a batch that has not settled. */\n | { readonly status: \"pending\" }\n /** Never seen, or cached and now expired. */\n | { readonly status: \"absent\" };\n\n// ===========================================================================\n// The knob factory.\n// ===========================================================================\n\n/**\n * Build a classify-batch knob from `config`.\n *\n * The verbs are pure and the whole composition is the four batteries'; the only\n * thing this factory adds is the native-batch request shape and the bookkeeping\n * that keeps one key out of two batches at once.\n */\nexport function createClassifyBatch<I, C extends string>(\n config: ClassifyBatchConfig<I, C>,\n) {\n type State = ClassifyBatchState<I, C>;\n type AskOk = JevOk<ItemQuestions<C>>;\n type Cmds = readonly ClassifyBatchCmd<C>[];\n\n const maxItems = config.maxItems ?? DEFAULT_CLASSIFY_MAX_ITEMS;\n const askCmd = jevAskCmdDef<ItemQuestions<C>>();\n const instructionsFor =\n config.instructions ??\n ((key: string): JevText =>\n `Classify the element of \\`state\\` whose key is \"${key}\".`);\n\n /** The batch's identity: its item keys, in arrival order. PURE. */\n function idOfBatch(batch: Batch<I>): string {\n return batch.id;\n }\n\n /** One batch's `questions` map — one choice question per item, keyed by `keyOf`. */\n function questionsFor(items: readonly I[]): ItemQuestions<C> {\n const questions: Record<string, ItemQuestion<C>> = {};\n for (const item of items) {\n const key = config.keyOf(item);\n questions[key] = {\n type: \"choice\",\n instructions: instructionsFor(key, item),\n criteria: config.criteria,\n };\n }\n return questions;\n }\n\n /**\n * The native Jev request for a batch: the item array IS the `state`, and the\n * questions map is the per-item fan-out. No envelope.\n */\n function requestFor(batch: Batch<I>): JevRequest<ItemQuestions<C>> {\n return {\n state: batch.items,\n model: config.model ?? DEFAULT_JEV_MODEL,\n questions: questionsFor(batch.items),\n };\n }\n\n const fanOut = createFanOut<\n Batch<I>,\n AskOk,\n ClassifyBatchCmd<C>,\n ClassifyBatchCmd<C>\n >({\n concurrency: config.concurrency,\n idOf: idOfBatch,\n of: (batch) => askCmd({ key: batch.id, input: requestFor(batch) }),\n });\n\n const window = createBatchWindow<I, FlushCmd<I>>({\n maxItems,\n maxMs: config.maxMs,\n flush: (items) => ({ type: \"classify_batch_flush\", items }),\n });\n\n /** The starting slice — each battery's own `init`, side by side. */\n function init(): State {\n return {\n window: window.init(),\n fanOut: fanOut.init(),\n cache: initCache<ItemAnswer<C>>(),\n failed: {},\n };\n }\n\n /** Every key currently buffered or in flight. PURE. */\n function keysInFlight(state: State): ReadonlySet<string> {\n const keys = new Set<string>();\n for (const item of state.window.buffer) keys.add(config.keyOf(item));\n for (const batch of state.fanOut.pending) {\n for (const item of batch.items) keys.add(config.keyOf(item));\n }\n for (const batch of state.fanOut.running) {\n for (const item of batch.items) keys.add(config.keyOf(item));\n }\n return keys;\n }\n\n /** The running batch a settle Msg's `key` addresses, or `undefined`. PURE. */\n function runningBatch(state: State, id: string): Batch<I> | undefined {\n return state.fanOut.running.find((batch) => batch.id === id);\n }\n\n /**\n * Hand a flushed window's items to fan-out. Fan-out returns the launch Cmds —\n * at most `concurrency` of them — so a window that flushes while the budget is\n * spent parks its batch in `pending` and launches nothing.\n */\n function scatter(\n state: State,\n flushed: readonly FlushCmd<I>[],\n ): readonly [State, Cmds] {\n if (flushed.length === 0) return [state, []];\n const batches = flushed.map((cmd) => ({\n id: cmd.items.map(config.keyOf).join(\"\\u0000\"),\n items: cmd.items,\n }));\n const [next, cmds] = fanOut.scatter(state.fanOut, batches);\n return [{ ...state, fanOut: next }, cmds];\n }\n\n /**\n * Offer `item` to the pipeline at `at`. PURE.\n *\n * An item whose key is cached, buffered, or already in a batch is DROPPED:\n * the cache hit is the whole point of the cache, and the other two are what\n * keeps one key out of two batches at once — which is the property that makes\n * a batch's id a usable identity and an answer's key unambiguous.\n *\n * An item that is NOT dropped loses its standing failure mark, exactly as\n * {@link onBatchOk} clears one: from the instant the key is buffered it is in\n * flight again, and a `failed` entry left standing would make `answerFor`\n * report the PREVIOUS attempt's error for the whole of the new one — telling a\n * host that polls it to stop waiting for work that is running.\n */\n function add(state: State, item: I, at: number): readonly [State, Cmds] {\n const key = config.keyOf(item);\n if (cacheHas(state.cache, key, at)) return [state, []];\n if (keysInFlight(state).has(key)) return [state, []];\n\n const failed: Record<string, JevAskErr> = { ...state.failed };\n delete failed[key];\n const [nextWindow, flushed] = window.add(state.window, item, at);\n return scatter({ ...state, failed, window: nextWindow }, flushed);\n }\n\n /** The time window closed: flush whatever is buffered. PURE. */\n function onWindow(state: State, at: number): readonly [State, Cmds] {\n const [nextWindow, flushed] = window.onWindow(state.window, at);\n return scatter({ ...state, window: nextWindow }, flushed);\n }\n\n /**\n * A batch settled OK. PURE.\n *\n * Every answer is written back to the cache with `ttlMs` at `msg.at`, the\n * batch's keys lose any standing failure mark, and fan-out backfills the freed\n * concurrency slot — so the returned Cmds are the next batches' asks.\n *\n * An answer arrives under the question id it was asked under, which is the\n * item's own key, so the write-back needs no positional matching between the\n * request `state` array and the answers map.\n */\n function onBatchOk(\n state: State,\n msg: ClassifyBatchOkMsg<C>,\n ): readonly [State, Cmds] {\n let cache = state.cache;\n for (const [key, answer] of Object.entries(msg.result.answers)) {\n cache = cacheSet(cache, key, answer, msg.at, config.ttlMs);\n }\n const failed: Record<string, JevAskErr> = { ...state.failed };\n for (const key of Object.keys(msg.result.answers)) delete failed[key];\n\n const [nextFanOut, cmds] = fanOut.itemOk(state.fanOut, msg.key, msg.result);\n return [{ ...state, cache, failed, fanOut: nextFanOut }, cmds];\n }\n\n /**\n * A batch settled `resilient_err`. PURE.\n *\n * Each of its keys is marked failed with the error that settled it and the\n * cache is NOT touched: a failure is not an answer, and writing one back under\n * `ttlMs` would poison every later `add` for that key for the whole TTL. The\n * key stays re-addable, because it is neither cached nor in flight once\n * fan-out has moved the batch to `failed`.\n */\n function onBatchErr(\n state: State,\n msg: ClassifyBatchErrMsg,\n ): readonly [State, Cmds] {\n const batch = runningBatch(state, msg.key);\n const failed: Record<string, JevAskErr> = { ...state.failed };\n if (batch !== undefined) {\n for (const item of batch.items) failed[config.keyOf(item)] = msg.error;\n }\n const [nextFanOut, cmds] = fanOut.itemErr(state.fanOut, msg.key, msg.error);\n return [{ ...state, failed, fanOut: nextFanOut }, cmds];\n }\n\n /** The eviction tick fired: drop every entry expired at `at`. PURE. */\n function onEvict(state: State, at: number): readonly [State, Cmds] {\n return [{ ...state, cache: evictExpired(state.cache, at) }, []];\n }\n\n /**\n * What is known about `key` at `at`. PURE, derived — it stores nothing.\n *\n * `at` is a parameter rather than a clock read because a TTL answer is only\n * an answer relative to an instant, and this module reads no clock anywhere.\n * The host passes the `at` of the Msg it is handling.\n */\n function answerFor(state: State, key: string, at: number): KeyAnswer<C> {\n const answer = cacheGet(state.cache, key, at);\n if (answer !== undefined) return { status: \"answered\", answer };\n const error = state.failed[key];\n if (error !== undefined) return { status: \"failed\", error };\n if (keysInFlight(state).has(key)) return { status: \"pending\" };\n return { status: \"absent\" };\n }\n\n /**\n * The Subs — the window's flush timer, plus the cache's eviction tick when\n * `evictEveryMs` is configured. Fan-out declares none (it runs no timers).\n */\n function subs(\n state: State,\n id = \"jev-classify-batch\",\n ): readonly (BatchWindowSub | CacheEvictionSub)[] {\n const windowSubs = window.subs(state.window, id);\n if (config.evictEveryMs === undefined) return windowSubs;\n return [...windowSubs, cacheEvictionSub(id, config.evictEveryMs)];\n }\n\n /** The `subscribe` cells the Subs above need. */\n function subscribers() {\n return { deadline: subscribeBatchWindow, cache: cacheEvictionSubscribe };\n }\n\n /**\n * The interpret handler for the ask Cmd. The port call, the status\n * classification and the parse are ALL `../ask`'s — this seam only builds the\n * ask knob around the questions the Cmd is carrying, because a batch's\n * question map is minted per batch while `createJevAsk` takes one map per\n * knob. The knob is built at the effect boundary, so nothing impure and\n * nothing closure-shaped ever reaches the slice.\n */\n function handlers(): {\n resilient_run: (\n cmd: ClassifyBatchCmd<C>,\n ) => Promise<ClassifyBatchOkMsg<C> | ClassifyBatchErrMsg>;\n } {\n return {\n resilient_run: (cmd) => {\n const request = cmd.input as JevRequest<ItemQuestions<C>>;\n const ask = createJevAsk<ItemQuestions<C>>({\n questions: request.questions,\n ...(config.port === undefined ? {} : { port: config.port }),\n ...(config.fallback === undefined\n ? {}\n : { fallback: config.fallback }),\n ...(config.model === undefined ? {} : { model: config.model }),\n });\n return ask.handlers().resilient_run(cmd);\n },\n };\n }\n\n return {\n init,\n add,\n onWindow,\n onBatchOk,\n onBatchErr,\n onEvict,\n answerFor,\n subs,\n subscribers,\n handlers,\n };\n}\n\n/** The bound knob {@link createClassifyBatch} returns. */\nexport type ClassifyBatchKnob<I, C extends string> = ReturnType<\n typeof createClassifyBatch<I, C>\n>;\n"]}