@anvia/core 1.1.1 → 1.2.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 (598) hide show
  1. package/README.md +226 -0
  2. package/dist/agent/agent-stream.js +7 -0
  3. package/dist/agent/agent-stream.js.map +1 -0
  4. package/dist/agent/agent-tool.js +24 -0
  5. package/dist/agent/agent-tool.js.map +1 -0
  6. package/dist/agent/agent.js +89 -0
  7. package/dist/agent/agent.js.map +1 -0
  8. package/dist/agent/errors.js +17 -0
  9. package/dist/agent/errors.js.map +1 -0
  10. package/dist/agent/ids.js +7 -0
  11. package/dist/agent/ids.js.map +1 -0
  12. package/dist/agent/index.d.ts +127 -9
  13. package/dist/agent/index.js +103 -21
  14. package/dist/agent/interactions/index.js +2 -2
  15. package/dist/agent/interactions.js +22 -0
  16. package/dist/agent/interactions.js.map +1 -0
  17. package/dist/agent/lifecycle.js +9 -0
  18. package/dist/agent/lifecycle.js.map +1 -0
  19. package/dist/agent/output-schema.js +10 -0
  20. package/dist/agent/output-schema.js.map +1 -0
  21. package/dist/agent/resolve-options.js +46 -0
  22. package/dist/agent/resolve-options.js.map +1 -0
  23. package/dist/agent/resolved-agent.js +92 -0
  24. package/dist/agent/resolved-agent.js.map +1 -0
  25. package/dist/agent/run-types.js +1 -0
  26. package/dist/agent/run-types.js.map +1 -0
  27. package/dist/agent/snapshot.js +17 -0
  28. package/dist/agent/snapshot.js.map +1 -0
  29. package/dist/agent/team/agent-team.js +98 -0
  30. package/dist/agent/team/agent-team.js.map +1 -0
  31. package/dist/agent/team/errors.js +9 -0
  32. package/dist/agent/team/errors.js.map +1 -0
  33. package/dist/agent/team/index.js +104 -0
  34. package/dist/agent/team/index.js.map +1 -0
  35. package/dist/agent/team/types.js +1 -0
  36. package/dist/agent/team/types.js.map +1 -0
  37. package/dist/agent/tool-catalog.js +37 -0
  38. package/dist/agent/tool-catalog.js.map +1 -0
  39. package/dist/agent/tool-state.js +11 -0
  40. package/dist/agent/tool-state.js.map +1 -0
  41. package/dist/agent/types.js +1 -0
  42. package/dist/agent/types.js.map +1 -0
  43. package/dist/agent/vector-context.js +10 -0
  44. package/dist/agent/vector-context.js.map +1 -0
  45. package/dist/{agent-DTmzs1Qr.d.ts → agent-C9VhENdj.d.ts} +2 -3
  46. package/dist/{chunk-2QZJTG2E.js → chunk-23GEYG2X.js} +11 -71
  47. package/dist/chunk-23GEYG2X.js.map +1 -0
  48. package/dist/{chunk-I3Q7XSBB.js → chunk-23LRXKQX.js} +6 -4
  49. package/dist/{chunk-I3Q7XSBB.js.map → chunk-23LRXKQX.js.map} +1 -1
  50. package/dist/{chunk-YK4WAAS4.js → chunk-2NLINXRF.js} +1 -1
  51. package/dist/{chunk-SPD4XVR7.js → chunk-2XSMGVBG.js} +1 -1
  52. package/dist/chunk-3J2CSVPR.js +1 -0
  53. package/dist/chunk-3J2CSVPR.js.map +1 -0
  54. package/dist/chunk-3P3YVJ7V.js +1 -0
  55. package/dist/chunk-3P3YVJ7V.js.map +1 -0
  56. package/dist/chunk-3TAQXJBC.js +107 -0
  57. package/dist/chunk-3TAQXJBC.js.map +1 -0
  58. package/dist/chunk-47NTHIVB.js +76 -0
  59. package/dist/chunk-47NTHIVB.js.map +1 -0
  60. package/dist/chunk-4AW2633B.js +9 -0
  61. package/dist/chunk-4AW2633B.js.map +1 -0
  62. package/dist/{chunk-3XQGVDU5.js → chunk-4C7AXYOM.js} +1 -1
  63. package/dist/{chunk-IZNOP6JG.js → chunk-4FIVU53H.js} +1 -1
  64. package/dist/chunk-4ITAV7YA.js +1 -0
  65. package/dist/chunk-4ITAV7YA.js.map +1 -0
  66. package/dist/{chunk-7JLAIN6E.js → chunk-4ONUNWGC.js} +2 -2
  67. package/dist/chunk-4UUIGAIX.js +1 -0
  68. package/dist/chunk-4UUIGAIX.js.map +1 -0
  69. package/dist/chunk-53TPAXYR.js +1 -0
  70. package/dist/chunk-53TPAXYR.js.map +1 -0
  71. package/dist/chunk-5AETKC4L.js +107 -0
  72. package/dist/chunk-5AETKC4L.js.map +1 -0
  73. package/dist/chunk-5I2NVRHC.js +146 -0
  74. package/dist/chunk-5I2NVRHC.js.map +1 -0
  75. package/dist/chunk-5IURMWFN.js +53 -0
  76. package/dist/chunk-5IURMWFN.js.map +1 -0
  77. package/dist/chunk-5M6GTA3T.js +1 -0
  78. package/dist/chunk-5M6GTA3T.js.map +1 -0
  79. package/dist/chunk-5N5W7CX7.js +18 -0
  80. package/dist/chunk-5N5W7CX7.js.map +1 -0
  81. package/dist/chunk-5P2YOQSA.js +355 -0
  82. package/dist/chunk-5P2YOQSA.js.map +1 -0
  83. package/dist/chunk-5S7T2URX.js +1 -0
  84. package/dist/chunk-5S7T2URX.js.map +1 -0
  85. package/dist/chunk-5V533R7F.js +19 -0
  86. package/dist/chunk-5V533R7F.js.map +1 -0
  87. package/dist/chunk-5WLIHNNJ.js +56 -0
  88. package/dist/chunk-5WLIHNNJ.js.map +1 -0
  89. package/dist/chunk-6BTJC3ES.js +37 -0
  90. package/dist/chunk-6BTJC3ES.js.map +1 -0
  91. package/dist/chunk-6N4ENZO4.js +24 -0
  92. package/dist/chunk-6N4ENZO4.js.map +1 -0
  93. package/dist/{chunk-4UQALF5Y.js → chunk-6RQYWZI3.js} +2 -36
  94. package/dist/chunk-6RQYWZI3.js.map +1 -0
  95. package/dist/chunk-6TAWRKFK.js +86 -0
  96. package/dist/chunk-6TAWRKFK.js.map +1 -0
  97. package/dist/chunk-7F53DOML.js +53 -0
  98. package/dist/chunk-7F53DOML.js.map +1 -0
  99. package/dist/chunk-7KAGWJ5M.js +112 -0
  100. package/dist/chunk-7KAGWJ5M.js.map +1 -0
  101. package/dist/chunk-7LBPRXZP.js +1 -0
  102. package/dist/chunk-7LBPRXZP.js.map +1 -0
  103. package/dist/chunk-A7BXVZXZ.js +25 -0
  104. package/dist/chunk-A7BXVZXZ.js.map +1 -0
  105. package/dist/chunk-B47EXUHL.js +67 -0
  106. package/dist/chunk-B47EXUHL.js.map +1 -0
  107. package/dist/chunk-B5JQDR33.js +14 -0
  108. package/dist/chunk-B5JQDR33.js.map +1 -0
  109. package/dist/chunk-B5YTCKUJ.js +158 -0
  110. package/dist/chunk-B5YTCKUJ.js.map +1 -0
  111. package/dist/chunk-BDDC72GF.js +189 -0
  112. package/dist/chunk-BDDC72GF.js.map +1 -0
  113. package/dist/chunk-BDKFFFVX.js +342 -0
  114. package/dist/chunk-BDKFFFVX.js.map +1 -0
  115. package/dist/{chunk-QGX73TSQ.js → chunk-BONQTXRQ.js} +3 -12
  116. package/dist/chunk-BONQTXRQ.js.map +1 -0
  117. package/dist/chunk-BUPC72Y2.js +1007 -0
  118. package/dist/chunk-BUPC72Y2.js.map +1 -0
  119. package/dist/chunk-CKKNO4XB.js +70 -0
  120. package/dist/chunk-CKKNO4XB.js.map +1 -0
  121. package/dist/chunk-CX7ZVTO5.js +22 -0
  122. package/dist/chunk-CX7ZVTO5.js.map +1 -0
  123. package/dist/chunk-DU4WA6LQ.js +1 -0
  124. package/dist/chunk-DU4WA6LQ.js.map +1 -0
  125. package/dist/chunk-EJR6VVB3.js +63 -0
  126. package/dist/chunk-EJR6VVB3.js.map +1 -0
  127. package/dist/chunk-EKZRAWBP.js +110 -0
  128. package/dist/chunk-EKZRAWBP.js.map +1 -0
  129. package/dist/chunk-ENZ2XX27.js +26 -0
  130. package/dist/chunk-ENZ2XX27.js.map +1 -0
  131. package/dist/chunk-EOAJBBII.js +1 -0
  132. package/dist/chunk-EOAJBBII.js.map +1 -0
  133. package/dist/chunk-ERN7P6Q4.js +1 -0
  134. package/dist/chunk-ERN7P6Q4.js.map +1 -0
  135. package/dist/chunk-ESOFEAYK.js +57 -0
  136. package/dist/chunk-ESOFEAYK.js.map +1 -0
  137. package/dist/chunk-ETYB5JO6.js +175 -0
  138. package/dist/chunk-ETYB5JO6.js.map +1 -0
  139. package/dist/chunk-EZR5AV3J.js +74 -0
  140. package/dist/chunk-EZR5AV3J.js.map +1 -0
  141. package/dist/chunk-F2OKLHGB.js +9 -0
  142. package/dist/chunk-F2OKLHGB.js.map +1 -0
  143. package/dist/chunk-F3E2RLC7.js +342 -0
  144. package/dist/chunk-F3E2RLC7.js.map +1 -0
  145. package/dist/chunk-FAPIZJS2.js +54 -0
  146. package/dist/chunk-FAPIZJS2.js.map +1 -0
  147. package/dist/chunk-GDJNOZ47.js +1 -0
  148. package/dist/chunk-GDJNOZ47.js.map +1 -0
  149. package/dist/chunk-GDY2Z2SZ.js +83 -0
  150. package/dist/chunk-GDY2Z2SZ.js.map +1 -0
  151. package/dist/chunk-GLMYZ6OA.js +20 -0
  152. package/dist/chunk-GLMYZ6OA.js.map +1 -0
  153. package/dist/{chunk-XEVOC433.js → chunk-GPVXCY5I.js} +2 -73
  154. package/dist/chunk-GPVXCY5I.js.map +1 -0
  155. package/dist/{chunk-KSKST3KP.js → chunk-H3H74RWJ.js} +1 -1
  156. package/dist/chunk-HAAGSIZH.js +89 -0
  157. package/dist/chunk-HAAGSIZH.js.map +1 -0
  158. package/dist/{chunk-K5L7R7XM.js → chunk-HHMLE3TZ.js} +6 -54
  159. package/dist/chunk-HHMLE3TZ.js.map +1 -0
  160. package/dist/{chunk-JLJMVRRE.js → chunk-HP34GRQX.js} +10 -83
  161. package/dist/chunk-HP34GRQX.js.map +1 -0
  162. package/dist/chunk-HTI343NP.js +1 -0
  163. package/dist/chunk-HTI343NP.js.map +1 -0
  164. package/dist/{chunk-T2C3CGDQ.js → chunk-HTI7DZJM.js} +6 -4
  165. package/dist/{chunk-T2C3CGDQ.js.map → chunk-HTI7DZJM.js.map} +1 -1
  166. package/dist/chunk-IDNL6IH4.js +294 -0
  167. package/dist/chunk-IDNL6IH4.js.map +1 -0
  168. package/dist/chunk-IV6YQTY2.js +47 -0
  169. package/dist/chunk-IV6YQTY2.js.map +1 -0
  170. package/dist/chunk-J4SINPUA.js +939 -0
  171. package/dist/chunk-J4SINPUA.js.map +1 -0
  172. package/dist/chunk-J6S6MT7O.js +32 -0
  173. package/dist/chunk-J6S6MT7O.js.map +1 -0
  174. package/dist/chunk-JB3RFK6K.js +168 -0
  175. package/dist/chunk-JB3RFK6K.js.map +1 -0
  176. package/dist/chunk-JBQNCUXA.js +34 -0
  177. package/dist/chunk-JBQNCUXA.js.map +1 -0
  178. package/dist/chunk-JMJFK3A4.js +1 -0
  179. package/dist/chunk-JMJFK3A4.js.map +1 -0
  180. package/dist/chunk-JMMZICU7.js +74 -0
  181. package/dist/chunk-JMMZICU7.js.map +1 -0
  182. package/dist/chunk-JOQ2T3QP.js +663 -0
  183. package/dist/chunk-JOQ2T3QP.js.map +1 -0
  184. package/dist/chunk-K4IBS7VB.js +55 -0
  185. package/dist/chunk-K4IBS7VB.js.map +1 -0
  186. package/dist/chunk-KBBQSP4M.js +16 -0
  187. package/dist/chunk-KBBQSP4M.js.map +1 -0
  188. package/dist/chunk-KFAVEL5F.js +68 -0
  189. package/dist/chunk-KFAVEL5F.js.map +1 -0
  190. package/dist/chunk-KITX3HDN.js +17 -0
  191. package/dist/chunk-KITX3HDN.js.map +1 -0
  192. package/dist/chunk-KO5NMTAM.js +1 -0
  193. package/dist/chunk-KO5NMTAM.js.map +1 -0
  194. package/dist/chunk-KY4VXIN2.js +118 -0
  195. package/dist/chunk-KY4VXIN2.js.map +1 -0
  196. package/dist/chunk-KZGSXJKU.js +29 -0
  197. package/dist/chunk-KZGSXJKU.js.map +1 -0
  198. package/dist/chunk-LAIATEUB.js +24 -0
  199. package/dist/chunk-LAIATEUB.js.map +1 -0
  200. package/dist/{chunk-OJBFDBLG.js → chunk-LBYJPMHC.js} +2 -2
  201. package/dist/chunk-LKIABZNR.js +49 -0
  202. package/dist/chunk-LKIABZNR.js.map +1 -0
  203. package/dist/chunk-LQJ4KHMY.js +23 -0
  204. package/dist/chunk-LQJ4KHMY.js.map +1 -0
  205. package/dist/chunk-MEN4AFDZ.js +1 -0
  206. package/dist/chunk-MEN4AFDZ.js.map +1 -0
  207. package/dist/chunk-MHOJJYDK.js +93 -0
  208. package/dist/chunk-MHOJJYDK.js.map +1 -0
  209. package/dist/chunk-MJCMKZFP.js +30 -0
  210. package/dist/chunk-MJCMKZFP.js.map +1 -0
  211. package/dist/chunk-MT3BLVYN.js +31 -0
  212. package/dist/chunk-MT3BLVYN.js.map +1 -0
  213. package/dist/chunk-NF6WBPFG.js +37 -0
  214. package/dist/chunk-NF6WBPFG.js.map +1 -0
  215. package/dist/chunk-NNEKBZSM.js +66 -0
  216. package/dist/chunk-NNEKBZSM.js.map +1 -0
  217. package/dist/chunk-NPJ2T3L5.js +19 -0
  218. package/dist/chunk-NPJ2T3L5.js.map +1 -0
  219. package/dist/chunk-NVALGVQG.js +150 -0
  220. package/dist/chunk-NVALGVQG.js.map +1 -0
  221. package/dist/chunk-OJF67RNM.js +1 -0
  222. package/dist/chunk-OJF67RNM.js.map +1 -0
  223. package/dist/chunk-PHLGGRHC.js +89 -0
  224. package/dist/chunk-PHLGGRHC.js.map +1 -0
  225. package/dist/chunk-PIMD4DYG.js +104 -0
  226. package/dist/chunk-PIMD4DYG.js.map +1 -0
  227. package/dist/chunk-PJNE75WC.js +1 -0
  228. package/dist/chunk-PJNE75WC.js.map +1 -0
  229. package/dist/{chunk-J6LVLV6P.js → chunk-PLDJCCVL.js} +1 -1
  230. package/dist/{chunk-3RWESPUG.js → chunk-POXHJF3H.js} +6 -51
  231. package/dist/chunk-POXHJF3H.js.map +1 -0
  232. package/dist/chunk-PPJ7SYQL.js +81 -0
  233. package/dist/chunk-PPJ7SYQL.js.map +1 -0
  234. package/dist/chunk-PT777EQ3.js +48 -0
  235. package/dist/chunk-PT777EQ3.js.map +1 -0
  236. package/dist/chunk-PYLPLFJZ.js +318 -0
  237. package/dist/chunk-PYLPLFJZ.js.map +1 -0
  238. package/dist/chunk-QEPBHHAP.js +41 -0
  239. package/dist/chunk-QEPBHHAP.js.map +1 -0
  240. package/dist/chunk-QHGYCYV6.js +91 -0
  241. package/dist/chunk-QHGYCYV6.js.map +1 -0
  242. package/dist/chunk-R6722CIU.js +28 -0
  243. package/dist/chunk-R6722CIU.js.map +1 -0
  244. package/dist/chunk-RA4YVN43.js +1 -0
  245. package/dist/chunk-RA4YVN43.js.map +1 -0
  246. package/dist/chunk-RT5LUEO3.js +2339 -0
  247. package/dist/chunk-RT5LUEO3.js.map +1 -0
  248. package/dist/chunk-RXKUIJ77.js +236 -0
  249. package/dist/chunk-RXKUIJ77.js.map +1 -0
  250. package/dist/chunk-SC4SUIEY.js +1 -0
  251. package/dist/chunk-SC4SUIEY.js.map +1 -0
  252. package/dist/chunk-SQAAVYJG.js +12 -0
  253. package/dist/chunk-SQAAVYJG.js.map +1 -0
  254. package/dist/chunk-SXE4J43E.js +59 -0
  255. package/dist/chunk-SXE4J43E.js.map +1 -0
  256. package/dist/{chunk-EFLT7XZD.js → chunk-SYULMZGL.js} +6 -4
  257. package/dist/{chunk-EFLT7XZD.js.map → chunk-SYULMZGL.js.map} +1 -1
  258. package/dist/chunk-T4KS577P.js +58 -0
  259. package/dist/chunk-T4KS577P.js.map +1 -0
  260. package/dist/chunk-TFIOU6UR.js +78 -0
  261. package/dist/chunk-TFIOU6UR.js.map +1 -0
  262. package/dist/chunk-TIZGADU4.js +375 -0
  263. package/dist/chunk-TIZGADU4.js.map +1 -0
  264. package/dist/chunk-TP3MCUXS.js +1 -0
  265. package/dist/chunk-TP3MCUXS.js.map +1 -0
  266. package/dist/chunk-TSPQD5HW.js +613 -0
  267. package/dist/chunk-TSPQD5HW.js.map +1 -0
  268. package/dist/{chunk-JTJU56ZV.js → chunk-UOGM62JL.js} +11 -7
  269. package/dist/{chunk-JTJU56ZV.js.map → chunk-UOGM62JL.js.map} +1 -1
  270. package/dist/chunk-USRKPEQN.js +55 -0
  271. package/dist/chunk-USRKPEQN.js.map +1 -0
  272. package/dist/chunk-UTAB3XQI.js +667 -0
  273. package/dist/chunk-UTAB3XQI.js.map +1 -0
  274. package/dist/chunk-V3FFZWF3.js +182 -0
  275. package/dist/chunk-V3FFZWF3.js.map +1 -0
  276. package/dist/chunk-V4OZ7ISA.js +9 -0
  277. package/dist/chunk-V4OZ7ISA.js.map +1 -0
  278. package/dist/chunk-VZ5ZZBNX.js +139 -0
  279. package/dist/chunk-VZ5ZZBNX.js.map +1 -0
  280. package/dist/{chunk-AHLKV6KP.js → chunk-WN6AVBO4.js} +1 -1
  281. package/dist/chunk-WXR5CWSC.js +1 -0
  282. package/dist/chunk-WXR5CWSC.js.map +1 -0
  283. package/dist/chunk-X6WS3XWL.js +36 -0
  284. package/dist/chunk-X6WS3XWL.js.map +1 -0
  285. package/dist/{chunk-Q5BCNYED.js → chunk-XJRNBTIV.js} +7 -4
  286. package/dist/chunk-XQV3XNVT.js +225 -0
  287. package/dist/chunk-XQV3XNVT.js.map +1 -0
  288. package/dist/chunk-XV3DH5GC.js +58 -0
  289. package/dist/chunk-XV3DH5GC.js.map +1 -0
  290. package/dist/chunk-YWRXOPHC.js +43 -0
  291. package/dist/chunk-YWRXOPHC.js.map +1 -0
  292. package/dist/chunk-YZVFIW5D.js +27 -0
  293. package/dist/chunk-YZVFIW5D.js.map +1 -0
  294. package/dist/chunk-ZHC5CD6J.js +33 -0
  295. package/dist/chunk-ZHC5CD6J.js.map +1 -0
  296. package/dist/chunk-ZPJFXRQZ.js +23 -0
  297. package/dist/chunk-ZPJFXRQZ.js.map +1 -0
  298. package/dist/chunk-ZPXOBQDS.js +57 -0
  299. package/dist/chunk-ZPXOBQDS.js.map +1 -0
  300. package/dist/chunk-ZUFS6R7L.js +155 -0
  301. package/dist/chunk-ZUFS6R7L.js.map +1 -0
  302. package/dist/chunk-ZXLCTQUX.js +62 -0
  303. package/dist/chunk-ZXLCTQUX.js.map +1 -0
  304. package/dist/chunk-ZYXMWEL4.js +59 -0
  305. package/dist/chunk-ZYXMWEL4.js.map +1 -0
  306. package/dist/completion/controls.js +11 -0
  307. package/dist/completion/controls.js.map +1 -0
  308. package/dist/completion/documents.js +9 -0
  309. package/dist/completion/documents.js.map +1 -0
  310. package/dist/completion/generate-completion.js +23 -0
  311. package/dist/completion/generate-completion.js.map +1 -0
  312. package/dist/completion/index.js +23 -12
  313. package/dist/completion/json.js +7 -0
  314. package/dist/completion/json.js.map +1 -0
  315. package/dist/completion/message-schema.js +18 -0
  316. package/dist/completion/message-schema.js.map +1 -0
  317. package/dist/completion/provider-output-error.js +12 -0
  318. package/dist/completion/provider-output-error.js.map +1 -0
  319. package/dist/completion/stream-accumulator.js +10 -0
  320. package/dist/completion/stream-accumulator.js.map +1 -0
  321. package/dist/completion/types.js +28 -0
  322. package/dist/completion/types.js.map +1 -0
  323. package/dist/documents/chunk-text.js +7 -0
  324. package/dist/documents/chunk-text.js.map +1 -0
  325. package/dist/documents/index.js +5 -2
  326. package/dist/documents/text-document.js +8 -0
  327. package/dist/documents/text-document.js.map +1 -0
  328. package/dist/embeddings/distance.js +17 -0
  329. package/dist/embeddings/distance.js.map +1 -0
  330. package/dist/embeddings/embed.js +18 -0
  331. package/dist/embeddings/embed.js.map +1 -0
  332. package/dist/embeddings/index.js +11 -6
  333. package/dist/embeddings/types.js +2 -0
  334. package/dist/embeddings/types.js.map +1 -0
  335. package/dist/evals/advanced-metrics.js +46 -0
  336. package/dist/evals/advanced-metrics.js.map +1 -0
  337. package/dist/evals/agent-target.js +10 -0
  338. package/dist/evals/agent-target.js.map +1 -0
  339. package/dist/evals/cli.js +40 -0
  340. package/dist/evals/cli.js.map +1 -0
  341. package/dist/evals/execution.js +15 -0
  342. package/dist/evals/execution.js.map +1 -0
  343. package/dist/evals/format.js +13 -0
  344. package/dist/evals/format.js.map +1 -0
  345. package/dist/evals/index.d.ts +4 -4
  346. package/dist/evals/index.js +87 -2660
  347. package/dist/evals/index.js.map +1 -1
  348. package/dist/evals/judge.js +27 -0
  349. package/dist/evals/judge.js.map +1 -0
  350. package/dist/evals/metric.js +7 -0
  351. package/dist/evals/metric.js.map +1 -0
  352. package/dist/evals/metrics.js +53 -0
  353. package/dist/evals/metrics.js.map +1 -0
  354. package/dist/evals/outcome.js +7 -0
  355. package/dist/evals/outcome.js.map +1 -0
  356. package/dist/evals/reporting.js +11 -0
  357. package/dist/evals/reporting.js.map +1 -0
  358. package/dist/evals/runner.js +29 -0
  359. package/dist/evals/runner.js.map +1 -0
  360. package/dist/evals/selectors.js +18 -0
  361. package/dist/evals/selectors.js.map +1 -0
  362. package/dist/evals/suite.js +11 -0
  363. package/dist/evals/suite.js.map +1 -0
  364. package/dist/evals/types.js +1 -0
  365. package/dist/evals/types.js.map +1 -0
  366. package/dist/extractor/extractor.js +23 -0
  367. package/dist/extractor/extractor.js.map +1 -0
  368. package/dist/extractor/index.js +16 -7
  369. package/dist/guardrails/actions.js +13 -0
  370. package/dist/guardrails/actions.js.map +1 -0
  371. package/dist/guardrails/index.d.ts +3 -4
  372. package/dist/guardrails/index.js +15 -7
  373. package/dist/guardrails/message.js +9 -0
  374. package/dist/guardrails/message.js.map +1 -0
  375. package/dist/guardrails/policy.js +17 -0
  376. package/dist/guardrails/policy.js.map +1 -0
  377. package/dist/guardrails/runtime.js +11 -0
  378. package/dist/guardrails/runtime.js.map +1 -0
  379. package/dist/guardrails/text.js +9 -0
  380. package/dist/guardrails/text.js.map +1 -0
  381. package/dist/guardrails/types.js +1 -0
  382. package/dist/guardrails/types.js.map +1 -0
  383. package/dist/hooks/control.js +17 -0
  384. package/dist/hooks/control.js.map +1 -0
  385. package/dist/hooks/index.js +19 -0
  386. package/dist/hooks/index.js.map +1 -0
  387. package/dist/hooks/types.js +2 -0
  388. package/dist/hooks/types.js.map +1 -0
  389. package/dist/image-generation/generate-image.js +11 -0
  390. package/dist/image-generation/generate-image.js.map +1 -0
  391. package/dist/image-generation/index.js +7 -4
  392. package/dist/image-generation/types.js +2 -0
  393. package/dist/image-generation/types.js.map +1 -0
  394. package/dist/index.d.ts +5 -7
  395. package/dist/index.js +163 -57
  396. package/dist/internal/abort.js +13 -0
  397. package/dist/internal/abort.js.map +1 -0
  398. package/dist/internal/agent-runtime/agent-run.js +81 -0
  399. package/dist/internal/agent-runtime/agent-run.js.map +1 -0
  400. package/dist/internal/agent-runtime/approval-request.js +1 -0
  401. package/dist/internal/agent-runtime/approval-request.js.map +1 -0
  402. package/dist/internal/agent-runtime/approval-requirement.js +9 -0
  403. package/dist/internal/agent-runtime/approval-requirement.js.map +1 -0
  404. package/dist/internal/agent-runtime/continuation-state.js +26 -0
  405. package/dist/internal/agent-runtime/continuation-state.js.map +1 -0
  406. package/dist/internal/agent-runtime/interaction-suspension.js +25 -0
  407. package/dist/internal/agent-runtime/interaction-suspension.js.map +1 -0
  408. package/dist/internal/agent-runtime/memory-scope.js +8 -0
  409. package/dist/internal/agent-runtime/memory-scope.js.map +1 -0
  410. package/dist/internal/agent-runtime/memory.js +24 -0
  411. package/dist/internal/agent-runtime/memory.js.map +1 -0
  412. package/dist/internal/agent-runtime/prepared-tool-call.js +19 -0
  413. package/dist/internal/agent-runtime/prepared-tool-call.js.map +1 -0
  414. package/dist/internal/agent-runtime/retrieval.js +35 -0
  415. package/dist/internal/agent-runtime/retrieval.js.map +1 -0
  416. package/dist/internal/agent-runtime/run-options.js +9 -0
  417. package/dist/internal/agent-runtime/run-options.js.map +1 -0
  418. package/dist/internal/agent-runtime/run-validation.js +9 -0
  419. package/dist/internal/agent-runtime/run-validation.js.map +1 -0
  420. package/dist/internal/agent-runtime/stream-events.js +11 -0
  421. package/dist/internal/agent-runtime/stream-events.js.map +1 -0
  422. package/dist/internal/agent-runtime/structured-output.js +13 -0
  423. package/dist/internal/agent-runtime/structured-output.js.map +1 -0
  424. package/dist/internal/agent-runtime/tool-execution.js +55 -0
  425. package/dist/internal/agent-runtime/tool-execution.js.map +1 -0
  426. package/dist/internal/agent.d.ts +5 -5
  427. package/dist/internal/agent.js +93 -57
  428. package/dist/internal/agent.js.map +1 -1
  429. package/dist/internal/async-queue.js +7 -0
  430. package/dist/internal/async-queue.js.map +1 -0
  431. package/dist/internal/completion-request.js +11 -0
  432. package/dist/internal/completion-request.js.map +1 -0
  433. package/dist/internal/concurrency.js +7 -0
  434. package/dist/internal/concurrency.js.map +1 -0
  435. package/dist/internal/json-object.js +8 -0
  436. package/dist/internal/json-object.js.map +1 -0
  437. package/dist/internal/rag-text.js +7 -0
  438. package/dist/internal/rag-text.js.map +1 -0
  439. package/dist/internal/record.js +7 -0
  440. package/dist/internal/record.js.map +1 -0
  441. package/dist/internal/team-runtime/coordination.js +12 -0
  442. package/dist/internal/team-runtime/coordination.js.map +1 -0
  443. package/dist/internal/team-runtime/member.js +26 -0
  444. package/dist/internal/team-runtime/member.js.map +1 -0
  445. package/dist/internal/team-runtime/policy.js +7 -0
  446. package/dist/internal/team-runtime/policy.js.map +1 -0
  447. package/dist/internal/team-runtime/run.js +95 -0
  448. package/dist/internal/team-runtime/run.js.map +1 -0
  449. package/dist/internal/team-runtime/stream.js +9 -0
  450. package/dist/internal/team-runtime/stream.js.map +1 -0
  451. package/dist/internal/team-runtime/tools.js +17 -0
  452. package/dist/internal/team-runtime/tools.js.map +1 -0
  453. package/dist/internal/type-utils.js +1 -0
  454. package/dist/internal/type-utils.js.map +1 -0
  455. package/dist/internal/vector-search-options.js +9 -0
  456. package/dist/internal/vector-search-options.js.map +1 -0
  457. package/dist/mcp/index.js +3 -1
  458. package/dist/mcp/tool.js +7 -0
  459. package/dist/mcp/tool.js.map +1 -0
  460. package/dist/mcp/types.js +2 -0
  461. package/dist/mcp/types.js.map +1 -0
  462. package/dist/memory/assert.js +11 -0
  463. package/dist/memory/assert.js.map +1 -0
  464. package/dist/memory/compaction.js +26 -0
  465. package/dist/memory/compaction.js.map +1 -0
  466. package/dist/memory/errors.js +9 -0
  467. package/dist/memory/errors.js.map +1 -0
  468. package/dist/memory/index.js +23 -10
  469. package/dist/memory/options.js +10 -0
  470. package/dist/memory/options.js.map +1 -0
  471. package/dist/memory/scope-key.js +7 -0
  472. package/dist/memory/scope-key.js.map +1 -0
  473. package/dist/memory/types.js +2 -0
  474. package/dist/memory/types.js.map +1 -0
  475. package/dist/{types-CRda8x7p.d.ts → middleware-CWjnMbiH.d.ts} +64 -5
  476. package/dist/model-call-options.js +1 -0
  477. package/dist/model-call-options.js.map +1 -0
  478. package/dist/model-listing/errors.js +7 -0
  479. package/dist/model-listing/errors.js.map +1 -0
  480. package/dist/model-listing/index.js +4 -13
  481. package/dist/model-listing/index.js.map +1 -1
  482. package/dist/model-listing/types.js +2 -0
  483. package/dist/model-listing/types.js.map +1 -0
  484. package/dist/observability/group.js +30 -0
  485. package/dist/observability/group.js.map +1 -0
  486. package/dist/observability/index.d.ts +4 -6
  487. package/dist/observability/index.js +16 -8
  488. package/dist/observability/snapshot.js +7 -0
  489. package/dist/observability/snapshot.js.map +1 -0
  490. package/dist/observability/types.js +1 -0
  491. package/dist/observability/types.js.map +1 -0
  492. package/dist/pipeline/errors.js +9 -0
  493. package/dist/pipeline/errors.js.map +1 -0
  494. package/dist/pipeline/graph.js +21 -0
  495. package/dist/pipeline/graph.js.map +1 -0
  496. package/dist/pipeline/index.d.ts +4 -6
  497. package/dist/pipeline/index.js +27 -805
  498. package/dist/pipeline/index.js.map +1 -1
  499. package/dist/pipeline/observability.js +15 -0
  500. package/dist/pipeline/observability.js.map +1 -0
  501. package/dist/pipeline/pipeline.js +30 -0
  502. package/dist/pipeline/pipeline.js.map +1 -0
  503. package/dist/pipeline/runtime.js +17 -0
  504. package/dist/pipeline/runtime.js.map +1 -0
  505. package/dist/pipeline/types.js +1 -0
  506. package/dist/pipeline/types.js.map +1 -0
  507. package/dist/retry.js +20 -0
  508. package/dist/retry.js.map +1 -0
  509. package/dist/schema/index.js +1 -0
  510. package/dist/schema/index.js.map +1 -0
  511. package/dist/schema/zod-schema.js +7 -0
  512. package/dist/schema/zod-schema.js.map +1 -0
  513. package/dist/skills/index.js +41 -12
  514. package/dist/skills/instructions.js +7 -0
  515. package/dist/skills/instructions.js.map +1 -0
  516. package/dist/skills/load.js +39 -0
  517. package/dist/skills/load.js.map +1 -0
  518. package/dist/skills/local.js +9 -0
  519. package/dist/skills/local.js.map +1 -0
  520. package/dist/skills/tools.js +37 -0
  521. package/dist/skills/tools.js.map +1 -0
  522. package/dist/skills/types.js +7 -0
  523. package/dist/skills/types.js.map +1 -0
  524. package/dist/speech-generation/generate-speech.js +11 -0
  525. package/dist/speech-generation/generate-speech.js.map +1 -0
  526. package/dist/speech-generation/index.js +7 -4
  527. package/dist/speech-generation/types.js +2 -0
  528. package/dist/speech-generation/types.js.map +1 -0
  529. package/dist/streaming/index.js +3 -37
  530. package/dist/streaming/index.js.map +1 -1
  531. package/dist/streaming/readable-stream.js +7 -0
  532. package/dist/streaming/readable-stream.js.map +1 -0
  533. package/dist/{text-CmjXxakS.d.ts → text-GbW4WYMg.d.ts} +1 -1
  534. package/dist/tool/create-tool.js +14 -0
  535. package/dist/tool/create-tool.js.map +1 -0
  536. package/dist/tool/dynamic-tools.js +35 -0
  537. package/dist/tool/dynamic-tools.js.map +1 -0
  538. package/dist/tool/errors.js +11 -0
  539. package/dist/tool/errors.js.map +1 -0
  540. package/dist/tool/index.d.ts +3 -2
  541. package/dist/tool/index.js +41 -15
  542. package/dist/tool/middleware.js +7 -0
  543. package/dist/tool/middleware.js.map +1 -0
  544. package/dist/tool/question-tool.js +17 -0
  545. package/dist/tool/question-tool.js.map +1 -0
  546. package/dist/tool/skill-tool-marker.js +9 -0
  547. package/dist/tool/skill-tool-marker.js.map +1 -0
  548. package/dist/tool/think-tool.js +15 -0
  549. package/dist/tool/think-tool.js.map +1 -0
  550. package/dist/tool/tool.js +17 -0
  551. package/dist/tool/tool.js.map +1 -0
  552. package/dist/transcription/index.js +7 -4
  553. package/dist/transcription/transcribe.js +11 -0
  554. package/dist/transcription/transcribe.js.map +1 -0
  555. package/dist/transcription/types.js +2 -0
  556. package/dist/transcription/types.js.map +1 -0
  557. package/dist/{types-h0EL6Xn0.d.ts → types-Bqw0AuFl.d.ts} +6 -2
  558. package/dist/vector-store/filter.js +9 -0
  559. package/dist/vector-store/filter.js.map +1 -0
  560. package/dist/vector-store/index.js +31 -11
  561. package/dist/vector-store/ingest.js +19 -0
  562. package/dist/vector-store/ingest.js.map +1 -0
  563. package/dist/vector-store/lsh.js +7 -0
  564. package/dist/vector-store/lsh.js.map +1 -0
  565. package/dist/vector-store/retrieve.js +15 -0
  566. package/dist/vector-store/retrieve.js.map +1 -0
  567. package/dist/vector-store/types.js +1 -0
  568. package/dist/vector-store/types.js.map +1 -0
  569. package/package.json +8 -5
  570. package/dist/chunk-2QZJTG2E.js.map +0 -1
  571. package/dist/chunk-3RWESPUG.js.map +0 -1
  572. package/dist/chunk-4UQALF5Y.js.map +0 -1
  573. package/dist/chunk-AZB6N7P4.js +0 -320
  574. package/dist/chunk-AZB6N7P4.js.map +0 -1
  575. package/dist/chunk-JLJMVRRE.js.map +0 -1
  576. package/dist/chunk-K5L7R7XM.js.map +0 -1
  577. package/dist/chunk-OI3LSMJG.js +0 -1545
  578. package/dist/chunk-OI3LSMJG.js.map +0 -1
  579. package/dist/chunk-QGX73TSQ.js.map +0 -1
  580. package/dist/chunk-XC3LVC4K.js +0 -753
  581. package/dist/chunk-XC3LVC4K.js.map +0 -1
  582. package/dist/chunk-XEVOC433.js.map +0 -1
  583. package/dist/chunk-XSV5C4R5.js +0 -400
  584. package/dist/chunk-XSV5C4R5.js.map +0 -1
  585. package/dist/chunk-XU54PLSD.js +0 -4786
  586. package/dist/chunk-XU54PLSD.js.map +0 -1
  587. package/dist/middleware-mY_lpjDp.d.ts +0 -59
  588. package/dist/type-utils-CtHVDRn_.d.ts +0 -6
  589. /package/dist/{chunk-YK4WAAS4.js.map → chunk-2NLINXRF.js.map} +0 -0
  590. /package/dist/{chunk-SPD4XVR7.js.map → chunk-2XSMGVBG.js.map} +0 -0
  591. /package/dist/{chunk-3XQGVDU5.js.map → chunk-4C7AXYOM.js.map} +0 -0
  592. /package/dist/{chunk-IZNOP6JG.js.map → chunk-4FIVU53H.js.map} +0 -0
  593. /package/dist/{chunk-7JLAIN6E.js.map → chunk-4ONUNWGC.js.map} +0 -0
  594. /package/dist/{chunk-KSKST3KP.js.map → chunk-H3H74RWJ.js.map} +0 -0
  595. /package/dist/{chunk-OJBFDBLG.js.map → chunk-LBYJPMHC.js.map} +0 -0
  596. /package/dist/{chunk-J6LVLV6P.js.map → chunk-PLDJCCVL.js.map} +0 -0
  597. /package/dist/{chunk-AHLKV6KP.js.map → chunk-WN6AVBO4.js.map} +0 -0
  598. /package/dist/{chunk-Q5BCNYED.js.map → chunk-XJRNBTIV.js.map} +0 -0
@@ -1,2669 +1,96 @@
1
1
  import {
2
- AgentRunBlockedError
3
- } from "../chunk-AHLKV6KP.js";
2
+ createEvalTypes,
3
+ defineEvalCases,
4
+ defineEvalSuite
5
+ } from "../chunk-CX7ZVTO5.js";
4
6
  import {
5
- cosineSimilarity,
6
- embedText
7
- } from "../chunk-K5L7R7XM.js";
7
+ EvalAssertionError,
8
+ assertEvalOutcomes,
9
+ assertEvalTotals,
10
+ defineEvalExpectations,
11
+ evalExitCode,
12
+ formatEvalResult,
13
+ printEvalResult,
14
+ runEvalCli
15
+ } from "../chunk-5P2YOQSA.js";
8
16
  import {
9
- mapWithConcurrency
10
- } from "../chunk-IZNOP6JG.js";
17
+ EvalFailFastError,
18
+ EvalReporterDispatchError,
19
+ runEvalSuite
20
+ } from "../chunk-JOQ2T3QP.js";
11
21
  import {
12
- extract
13
- } from "../chunk-JTJU56ZV.js";
14
- import "../chunk-4UQALF5Y.js";
22
+ defaultEvalTraceSelector,
23
+ projectEvalOutcome,
24
+ resolveEvalTraceRef
25
+ } from "../chunk-PHLGGRHC.js";
15
26
  import {
16
- Usage
17
- } from "../chunk-OI3LSMJG.js";
18
- import "../chunk-7JLAIN6E.js";
19
- import "../chunk-QGX73TSQ.js";
27
+ EvalAbortError,
28
+ EvalTimeoutError
29
+ } from "../chunk-JMMZICU7.js";
20
30
  import {
21
- isJsonValue
22
- } from "../chunk-3XQGVDU5.js";
23
- import "../chunk-3RWESPUG.js";
24
-
25
- // src/evals/advanced-metrics.ts
26
- import { z } from "zod";
27
-
28
- // src/evals/format.ts
29
- function defaultOutputValue(output) {
30
- if (typeof output === "object" && output !== null && "output" in output) {
31
- return output.output;
32
- }
33
- return output;
34
- }
35
- function evalValuesEqual(left, right) {
36
- return deepEqual(left, right, /* @__PURE__ */ new WeakMap());
37
- }
38
- function formatValue(value) {
39
- if (typeof value === "string") {
40
- return value;
41
- }
42
- try {
43
- return JSON.stringify(value) ?? String(value);
44
- } catch {
45
- return String(value);
46
- }
47
- }
48
- function errorMessage(error) {
49
- return error instanceof Error ? error.message : String(error);
50
- }
51
- function deepEqual(left, right, seen) {
52
- if (Object.is(left, right)) return true;
53
- if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) {
54
- return false;
55
- }
56
- if (Object.getPrototypeOf(left) !== Object.getPrototypeOf(right)) return false;
57
- if (left instanceof Date && right instanceof Date) return left.getTime() === right.getTime();
58
- if (left instanceof RegExp && right instanceof RegExp) return String(left) === String(right);
59
- if (!Array.isArray(left) && Object.getPrototypeOf(left) !== Object.prototype && Object.getPrototypeOf(left) !== null) {
60
- return false;
61
- }
62
- if (seen.get(left) === right) return true;
63
- seen.set(left, right);
64
- const leftKeys = Reflect.ownKeys(left);
65
- const rightKeys = Reflect.ownKeys(right);
66
- if (leftKeys.length !== rightKeys.length) return false;
67
- for (const key of leftKeys) {
68
- if (!Object.hasOwn(right, key)) return false;
69
- if (!deepEqual(
70
- left[key],
71
- right[key],
72
- seen
73
- )) {
74
- return false;
75
- }
76
- }
77
- return true;
78
- }
79
-
80
- // src/evals/judge.ts
81
- async function runJudge(args) {
82
- const result = await extract({
83
- model: args.model,
84
- outputSchema: args.schema,
85
- instructions: args.instructions,
86
- text: args.prompt,
87
- temperature: 0,
88
- retries: args.retries <= 0 ? void 0 : { maxAttempts: Math.trunc(args.retries) + 1 }
89
- });
90
- return { data: result.output, usage: result.usage };
91
- }
92
- function addUsage(...values) {
93
- return values.reduce((total, usage) => Usage.add(total, usage), Usage.empty());
94
- }
95
- function evaluationMetadata(details, usage) {
96
- const evaluation = {
97
- ...details,
98
- usage: usageToJson(usage)
99
- };
100
- return { evaluation };
101
- }
102
- function usageToJson(usage) {
103
- const value = {
104
- inputTokens: usage.inputTokens,
105
- outputTokens: usage.outputTokens,
106
- totalTokens: usage.totalTokens,
107
- cachedInputTokens: usage.cachedInputTokens,
108
- cacheCreationInputTokens: usage.cacheCreationInputTokens
109
- };
110
- if (usage.details !== void 0) {
111
- value.details = { ...usage.details };
112
- }
113
- return value;
114
- }
115
-
116
- // src/evals/outcome.ts
117
- var EvalOutcome = {
118
- pass(score, options = {}) {
119
- const outcome = {
120
- outcome: "pass"
121
- };
122
- if (score !== void 0) {
123
- outcome.score = score;
124
- }
125
- if (options.comment !== void 0) {
126
- outcome.comment = options.comment;
127
- }
128
- if (options.metadata !== void 0) {
129
- outcome.metadata = options.metadata;
130
- }
131
- if (options.usage !== void 0) {
132
- outcome.usage = options.usage;
133
- }
134
- return outcome;
135
- },
136
- fail(score, options = {}) {
137
- const outcome = {
138
- outcome: "fail"
139
- };
140
- if (score !== void 0) {
141
- outcome.score = score;
142
- }
143
- if (options.comment !== void 0) {
144
- outcome.comment = options.comment;
145
- }
146
- if (options.metadata !== void 0) {
147
- outcome.metadata = options.metadata;
148
- }
149
- if (options.usage !== void 0) {
150
- outcome.usage = options.usage;
151
- }
152
- return outcome;
153
- },
154
- invalid(reason, options = {}) {
155
- const outcome = {
156
- outcome: "invalid",
157
- reason
158
- };
159
- if (options.score !== void 0) {
160
- outcome.score = options.score;
161
- }
162
- if (options.comment !== void 0) outcome.comment = options.comment;
163
- if (options.metadata !== void 0) outcome.metadata = options.metadata;
164
- if (options.usage !== void 0) outcome.usage = options.usage;
165
- if (options.kind !== void 0) outcome.kind = options.kind;
166
- if (options.error !== void 0) outcome.error = options.error;
167
- return outcome;
168
- },
169
- fromError(error, kind = "metric") {
170
- const reason = error instanceof Error ? error.message : String(error);
171
- return EvalOutcome.invalid(reason, { kind, error });
172
- }
173
- };
174
-
175
- // src/evals/selectors.ts
176
- function selectPromptOutput(args) {
177
- if (typeof args.output !== "object" || args.output === null || !("output" in args.output) || typeof args.output.output !== "string") {
178
- throw new TypeError("selectPromptOutput requires an output object with a string output field.");
179
- }
180
- return args.output.output;
181
- }
182
- function selectEvalCaseIds(result, outcomes = ["fail", "invalid"]) {
183
- const selected = new Set(outcomes);
184
- return result.results.filter((caseResult) => selected.has(caseResult.outcome)).map((caseResult) => caseResult.case.id);
185
- }
186
- async function resolveActual(selector, args) {
187
- return selector === void 0 ? defaultOutputValue(args.output) : selector(args);
188
- }
189
- async function resolveActualText(selector, args) {
190
- const value = selector === void 0 ? defaultOutputValue(args.output) : await selector(args);
191
- if (typeof value === "string") return value;
192
- try {
193
- const serialized = JSON.stringify(value);
194
- if (serialized !== void 0) return serialized;
195
- } catch {
196
- }
197
- throw new TypeError("Text metric actual value must be a string or JSON-serializable value.");
198
- }
199
- async function resolveExpected(selectorOrValue, args) {
200
- if (selectorOrValue === void 0) {
201
- return args.case.expected;
202
- }
203
- return typeof selectorOrValue === "function" ? selectorOrValue(args) : selectorOrValue;
204
- }
205
- async function resolveJudgePrompt(selector, args) {
206
- if (selector !== void 0) {
207
- return selector(args);
208
- }
209
- return [
210
- `Suite: ${args.suiteName}`,
211
- `Case: ${args.case.id}`,
212
- `Input: ${formatValue(args.case.input)}`,
213
- `Expected: ${formatValue(args.case.expected)}`,
214
- `Output: ${formatValue(defaultOutputValue(args.output))}`
215
- ].join("\n\n");
216
- }
217
-
218
- // src/evals/advanced-metrics.ts
219
- var statementsSchema = z.object({ statements: z.array(z.string()) });
220
- var factsSchema = z.object({ facts: z.array(z.string()) });
221
- var questionsSchema = z.object({ questions: z.array(z.string()) });
222
- var answersSchema = z.object({ answers: z.array(z.enum(["yes", "no"])) });
223
- var verdictsSchema = z.object({
224
- verdicts: z.array(
225
- z.object({
226
- verdict: z.enum(["yes", "no", "idk"]),
227
- reason: z.string().optional()
228
- })
229
- )
230
- });
231
- var binaryVerdictsSchema = z.object({
232
- verdicts: z.array(
233
- z.object({
234
- verdict: z.enum(["yes", "no"]),
235
- reason: z.string()
236
- })
237
- )
238
- });
239
- var binaryVerdictSchema = z.object({
240
- verdict: z.enum(["yes", "no"]),
241
- reason: z.string()
242
- });
243
- var reasonSchema = z.object({ reason: z.string() });
244
- var abstentionJudgmentSchema = z.object({
245
- behavior: z.enum(["abstention", "confident_answer"]),
246
- grounded: z.boolean(),
247
- reason: z.string()
248
- });
249
- function answerRelevancy(options) {
250
- const config = metricConfig(options, "answer_relevancy");
251
- return numericMetric(config.name, config, "higher_is_better", async (args) => {
252
- try {
253
- const input = await resolveInput(options.input, args);
254
- const actual = await resolveActualText(options.actual, args);
255
- const statementResult = await runJudge({
256
- model: options.model,
257
- schema: statementsSchema,
258
- instructions: "Break the answer into concise, independently assessable statements. Return every substantive statement using the schema.",
259
- prompt: `Answer:
260
- ${actual}`,
261
- retries: config.retries
262
- });
263
- const statements = statementResult.data.statements;
264
- let verdicts = [];
265
- let usage = statementResult.usage;
266
- if (statements.length > 0) {
267
- const verdictResult = await runJudge({
268
- model: options.model,
269
- schema: verdictsSchema,
270
- instructions: "Classify each answer statement for relevance to the user input. Use yes for relevant, no for irrelevant, and idk only when relevance is genuinely indeterminate. Preserve order and return one verdict per statement.",
271
- prompt: jsonPrompt({ input, statements }),
272
- retries: config.retries
273
- });
274
- verdicts = verdictResult.data.verdicts;
275
- assertSameLength("answer relevancy verdicts", statements, verdicts);
276
- usage = addUsage(usage, verdictResult.usage);
277
- }
278
- const score = verdicts.length === 0 ? 1 : verdicts.filter((verdict) => verdict.verdict !== "no").length / verdicts.length;
279
- const serializedVerdicts = serializeVerdicts(verdicts);
280
- const reasonResult = await maybeReason({
281
- model: options.model,
282
- includeReason: config.includeReason,
283
- retries: config.retries,
284
- metric: "answer relevancy",
285
- score,
286
- evidence: { input, verdicts: serializedVerdicts }
287
- });
288
- usage = addUsage(usage, reasonResult.usage);
289
- return higherOutcome({
290
- score,
291
- threshold: config.threshold,
292
- strictMode: config.strictMode,
293
- comment: reasonResult.reason,
294
- details: { statements, verdicts: serializedVerdicts },
295
- usage
296
- });
297
- } catch (error) {
298
- return EvalOutcome.fromError(error);
299
- }
300
- });
301
- }
302
- function promptAlignment(options) {
303
- if (options.promptInstructions.length === 0) {
304
- throw new TypeError("promptAlignment requires at least one prompt instruction.");
305
- }
306
- const config = metricConfig(options, "prompt_alignment");
307
- return numericMetric(config.name, config, "higher_is_better", async (args) => {
308
- try {
309
- const input = await resolveInput(options.input, args);
310
- const actual = await resolveActualText(options.actual, args);
311
- const verdictResult = await runJudge({
312
- model: options.model,
313
- schema: binaryVerdictsSchema,
314
- instructions: "Determine whether the answer follows each prompt instruction. Preserve order and return exactly one yes or no verdict per instruction.",
315
- prompt: jsonPrompt({ input, actual, instructions: options.promptInstructions }),
316
- retries: config.retries
317
- });
318
- const verdicts = verdictResult.data.verdicts;
319
- assertSameLength("prompt alignment verdicts", options.promptInstructions, verdicts);
320
- const score = verdicts.filter((verdict) => verdict.verdict === "yes").length / verdicts.length;
321
- const reasonResult = await maybeReason({
322
- model: options.model,
323
- includeReason: config.includeReason,
324
- retries: config.retries,
325
- metric: "prompt alignment",
326
- score,
327
- evidence: { verdicts }
328
- });
329
- const usage = addUsage(verdictResult.usage, reasonResult.usage);
330
- return higherOutcome({
331
- score,
332
- threshold: config.threshold,
333
- strictMode: config.strictMode,
334
- comment: reasonResult.reason,
335
- details: { promptInstructions: options.promptInstructions, verdicts },
336
- usage
337
- });
338
- } catch (error) {
339
- return EvalOutcome.fromError(error);
340
- }
341
- });
342
- }
343
- function jsonCorrectness(options) {
344
- const threshold = validateThreshold(options.threshold ?? 0.5);
345
- const retries = validateRetries(options.retries ?? 0);
346
- const includeReason = options.includeReason ?? true;
347
- const strictMode = options.strictMode ?? true;
348
- return numericMetric(
349
- options.name ?? "json_correctness",
350
- {
351
- threshold: strictMode ? 1 : threshold,
352
- required: options.required ?? true
353
- },
354
- "higher_is_better",
355
- async (args) => {
356
- try {
357
- const actual = await resolveActualText(options.actual, args);
358
- let parsed;
359
- let validationError;
360
- try {
361
- parsed = JSON.parse(actual);
362
- if (!isJsonValue(parsed)) {
363
- throw new TypeError("Generated output is not a JSON value.");
364
- }
365
- const result = options.schema.safeParse(parsed);
366
- if (!result.success) {
367
- validationError = z.prettifyError(result.error);
368
- }
369
- } catch (error) {
370
- validationError = errorMessage(error);
371
- }
372
- const score = validationError === void 0 ? 1 : 0;
373
- let comment;
374
- let usage = Usage.empty();
375
- if (includeReason) {
376
- if (score === 1) {
377
- comment = "The generated JSON is syntactically valid and matches the expected schema.";
378
- } else if (options.model === void 0) {
379
- comment = validationError;
380
- } else {
381
- const reasonResult = await runJudge({
382
- model: options.model,
383
- schema: reasonSchema,
384
- instructions: "Briefly explain why the generated JSON does not match the expected schema. Focus on actionable syntax, field, and type problems.",
385
- prompt: jsonPrompt({ actual, validationError }),
386
- retries
387
- });
388
- comment = reasonResult.data.reason;
389
- usage = reasonResult.usage;
390
- }
391
- }
392
- return higherOutcome({
393
- score,
394
- threshold,
395
- strictMode,
396
- comment,
397
- details: validationError === void 0 ? {} : { validationError },
398
- usage
399
- });
400
- } catch (error) {
401
- return EvalOutcome.fromError(error);
402
- }
403
- }
404
- );
405
- }
406
- function hallucination(options) {
407
- const config = metricConfig(options, "hallucination");
408
- return numericMetric(config.name, config, "lower_is_better", async (args) => {
409
- try {
410
- const actual = await resolveActualText(options.actual, args);
411
- const context = await resolveStringList(options.context, args.case.context, args, "context");
412
- const verdictResult = await runJudge({
413
- model: options.model,
414
- schema: binaryVerdictsSchema,
415
- instructions: "Compare the answer with each trusted context. Use yes when the answer is factually aligned with that context and no when it contradicts it. Preserve order and return one verdict per context.",
416
- prompt: jsonPrompt({ actual, context }),
417
- retries: config.retries
418
- });
419
- const verdicts = verdictResult.data.verdicts;
420
- assertSameLength("hallucination verdicts", context, verdicts);
421
- const score = verdicts.filter((verdict) => verdict.verdict === "no").length / verdicts.length;
422
- const reasonResult = await maybeReason({
423
- model: options.model,
424
- includeReason: config.includeReason,
425
- retries: config.retries,
426
- metric: "hallucination",
427
- score,
428
- evidence: { verdicts }
429
- });
430
- const usage = addUsage(verdictResult.usage, reasonResult.usage);
431
- return lowerOutcome({
432
- score,
433
- threshold: config.threshold,
434
- strictMode: config.strictMode,
435
- comment: reasonResult.reason,
436
- details: { verdicts },
437
- usage
438
- });
439
- } catch (error) {
440
- return EvalOutcome.fromError(error);
441
- }
442
- });
443
- }
444
- function faithfulness(options) {
445
- const config = metricConfig(options, "faithfulness");
446
- const truthsExtractionLimit = validateOptionalNonNegativeInteger(
447
- options.truthsExtractionLimit,
448
- "truthsExtractionLimit"
449
- );
450
- return numericMetric(config.name, config, "higher_is_better", async (args) => {
451
- try {
452
- const actual = await resolveActualText(options.actual, args);
453
- const retrievalContext = await resolveStringList(
454
- options.retrievalContext,
455
- args.case.retrievalContext,
456
- args,
457
- "retrievalContext"
458
- );
459
- const [truthResult, claimResult] = await Promise.all([
460
- runJudge({
461
- model: options.model,
462
- schema: factsSchema,
463
- instructions: truthsExtractionInstructions(truthsExtractionLimit),
464
- prompt: jsonPrompt({ retrievalContext }),
465
- retries: config.retries
466
- }),
467
- runJudge({
468
- model: options.model,
469
- schema: factsSchema,
470
- instructions: "Extract every concise factual claim made by the answer. Return claims in the facts array and omit opinions or purely stylistic text.",
471
- prompt: `Answer:
472
- ${actual}`,
473
- retries: config.retries
474
- })
475
- ]);
476
- const truths = limitValues(truthResult.data.facts, truthsExtractionLimit);
477
- const claims = claimResult.data.facts;
478
- let verdicts = [];
479
- let usage = addUsage(truthResult.usage, claimResult.usage);
480
- if (claims.length > 0) {
481
- const verdictResult = await runJudge({
482
- model: options.model,
483
- schema: verdictsSchema,
484
- instructions: "Determine whether each answer claim is supported by the supplied truths. Use yes for supported, no for contradicted or unsupported, and idk for genuinely ambiguous support. Preserve order and return one verdict per claim.",
485
- prompt: jsonPrompt({ truths, claims }),
486
- retries: config.retries
487
- });
488
- verdicts = verdictResult.data.verdicts;
489
- assertSameLength("faithfulness verdicts", claims, verdicts);
490
- usage = addUsage(usage, verdictResult.usage);
491
- }
492
- const penalizeAmbiguousClaims = options.penalizeAmbiguousClaims ?? false;
493
- const supported = verdicts.filter(
494
- (verdict) => verdict.verdict === "yes" || verdict.verdict === "idk" && !penalizeAmbiguousClaims
495
- ).length;
496
- const score = verdicts.length === 0 ? 1 : supported / verdicts.length;
497
- const serializedVerdicts = serializeVerdicts(verdicts);
498
- const reasonResult = await maybeReason({
499
- model: options.model,
500
- includeReason: config.includeReason,
501
- retries: config.retries,
502
- metric: "faithfulness",
503
- score,
504
- evidence: { verdicts: serializedVerdicts, penalizeAmbiguousClaims }
505
- });
506
- usage = addUsage(usage, reasonResult.usage);
507
- return higherOutcome({
508
- score,
509
- threshold: config.threshold,
510
- strictMode: config.strictMode,
511
- comment: reasonResult.reason,
512
- details: { truths, claims, verdicts: serializedVerdicts, penalizeAmbiguousClaims },
513
- usage
514
- });
515
- } catch (error) {
516
- return EvalOutcome.fromError(error);
517
- }
518
- });
519
- }
520
- function abstention(options) {
521
- const retries = validateRetries(options.retries ?? 0);
522
- return {
523
- name: options.name ?? "abstention",
524
- required: options.required ?? true,
525
- dataType: "CATEGORICAL",
526
- async evaluate(args) {
527
- try {
528
- const actual = await resolveActualText(options.actual, args);
529
- const shouldAbstain = await resolveExpected(options.shouldAbstain, args);
530
- if (typeof shouldAbstain !== "boolean") {
531
- return EvalOutcome.invalid("abstention shouldAbstain must resolve to a boolean.");
532
- }
533
- const context = await resolveAbstentionContext(options.context, args);
534
- if (!shouldAbstain && context.length === 0) {
535
- return EvalOutcome.invalid(
536
- "abstention context must be non-empty when shouldAbstain is false."
537
- );
538
- }
539
- const judgment = await runJudge({
540
- model: options.model,
541
- schema: abstentionJudgmentSchema,
542
- instructions: "Classify whether the answer abstains or gives a confident answer. For a confident answer, grounded is true only when every substantive factual claim is supported by the supplied context. For an abstention, set grounded to false. Return a concise evidence-based reason.",
543
- prompt: jsonPrompt({ actual, context }),
544
- retries
545
- });
546
- const category = abstentionCategory(
547
- shouldAbstain,
548
- judgment.data.behavior,
549
- judgment.data.grounded
550
- );
551
- const outcomeOptions = {
552
- comment: options.includeReason === false ? void 0 : judgment.data.reason,
553
- metadata: evaluationMetadata(
554
- {
555
- behavior: judgment.data.behavior,
556
- grounded: judgment.data.grounded,
557
- shouldAbstain
558
- },
559
- judgment.usage
560
- ),
561
- usage: judgment.usage
562
- };
563
- return category === "correct_abstention" || category === "correct_grounded_answer" ? EvalOutcome.pass(category, outcomeOptions) : EvalOutcome.fail(category, outcomeOptions);
564
- } catch (error) {
565
- return EvalOutcome.fromError(error);
566
- }
567
- }
568
- };
569
- }
570
- async function resolveAbstentionContext(selectorOrValue, args) {
571
- const context = selectorOrValue === void 0 ? args.case.retrievalContext ?? [] : typeof selectorOrValue === "function" ? await selectorOrValue(args) : selectorOrValue;
572
- if (!Array.isArray(context) || context.some((value) => typeof value !== "string")) {
573
- throw new TypeError("abstention context must be an array of strings.");
574
- }
575
- return context;
576
- }
577
- function abstentionCategory(shouldAbstain, behavior, grounded) {
578
- if (behavior === "abstention") {
579
- return shouldAbstain ? "correct_abstention" : "unnecessary_abstention";
580
- }
581
- if (shouldAbstain || !grounded) return "unsupported_confident_answer";
582
- return "correct_grounded_answer";
583
- }
584
- function summarization(options) {
585
- const config = metricConfig(options, "summarization");
586
- const questionCount = validatePositiveInteger(options.questionCount ?? 5, "questionCount");
587
- const truthsExtractionLimit = validateOptionalNonNegativeInteger(
588
- options.truthsExtractionLimit,
589
- "truthsExtractionLimit"
590
- );
591
- const suppliedQuestions = options.assessmentQuestions !== void 0 && options.assessmentQuestions.length > 0 ? [...options.assessmentQuestions] : void 0;
592
- return numericMetric(config.name, config, "higher_is_better", async (args) => {
593
- try {
594
- const input = await resolveInput(options.input, args);
595
- const actual = await resolveActualText(options.actual, args);
596
- const questionPromise = suppliedQuestions === void 0 ? runJudge({
597
- model: options.model,
598
- schema: questionsSchema,
599
- instructions: `Generate exactly ${questionCount} important yes-or-no assessment questions whose answers capture the source text's essential information.`,
600
- prompt: `Source text:
601
- ${input}`,
602
- retries: config.retries
603
- }) : Promise.resolve({
604
- data: { questions: suppliedQuestions },
605
- usage: Usage.empty()
606
- });
607
- const [truthResult, claimResult, questionResult] = await Promise.all([
608
- runJudge({
609
- model: options.model,
610
- schema: factsSchema,
611
- instructions: truthsExtractionInstructions(truthsExtractionLimit),
612
- prompt: `Source text:
613
- ${input}`,
614
- retries: config.retries
615
- }),
616
- runJudge({
617
- model: options.model,
618
- schema: factsSchema,
619
- instructions: "Extract every concise factual claim made by the summary. Return claims in the facts array.",
620
- prompt: `Summary:
621
- ${actual}`,
622
- retries: config.retries
623
- }),
624
- questionPromise
625
- ]);
626
- const truths = limitValues(truthResult.data.facts, truthsExtractionLimit);
627
- const claims = claimResult.data.facts;
628
- const questions = questionResult.data.questions;
629
- if (questions.length === 0) {
630
- throw new Error("Summarization assessment questions must not be empty.");
631
- }
632
- const sourceAnswerPromise = runJudge({
633
- model: options.model,
634
- schema: answersSchema,
635
- instructions: "Answer each assessment question using only the supplied text. Return one yes or no answer per question in the same order.",
636
- prompt: jsonPrompt({ questions, text: input }),
637
- retries: config.retries
638
- });
639
- const summaryAnswerPromise = runJudge({
640
- model: options.model,
641
- schema: answersSchema,
642
- instructions: "Answer each assessment question using only the supplied text. Return one yes or no answer per question in the same order.",
643
- prompt: jsonPrompt({ questions, text: actual }),
644
- retries: config.retries
645
- });
646
- const alignmentPromise = claims.length === 0 ? Promise.resolve({ data: { verdicts: [] }, usage: Usage.empty() }) : runJudge({
647
- model: options.model,
648
- schema: verdictsSchema,
649
- instructions: "Determine whether each summary claim is supported by the source truths. Use yes for supported, no for contradicted, and idk for unsupported filler or ambiguity. Preserve order.",
650
- prompt: jsonPrompt({ truths, claims }),
651
- retries: config.retries
652
- });
653
- const [sourceAnswerResult, summaryAnswerResult, alignmentResult] = await Promise.all([
654
- sourceAnswerPromise,
655
- summaryAnswerPromise,
656
- alignmentPromise
657
- ]);
658
- assertSameLength("source assessment answers", questions, sourceAnswerResult.data.answers);
659
- assertSameLength("summary assessment answers", questions, summaryAnswerResult.data.answers);
660
- assertSameLength("summarization alignment verdicts", claims, alignmentResult.data.verdicts);
661
- const alignmentVerdicts = alignmentResult.data.verdicts;
662
- const alignmentScore = alignmentVerdicts.length === 0 ? 0 : alignmentVerdicts.filter((verdict) => verdict.verdict === "yes").length / alignmentVerdicts.length;
663
- let coverageTotal = 0;
664
- let coverageMatched = 0;
665
- const coverageVerdicts = questions.map((question, index) => {
666
- const originalVerdict = sourceAnswerResult.data.answers[index];
667
- const summaryVerdict = summaryAnswerResult.data.answers[index];
668
- if (originalVerdict === "yes") {
669
- coverageTotal += 1;
670
- if (summaryVerdict === "yes") coverageMatched += 1;
671
- }
672
- return { question, originalVerdict, summaryVerdict };
673
- });
674
- const coverageScore = coverageTotal === 0 ? 0 : coverageMatched / coverageTotal;
675
- const score = Math.min(alignmentScore, coverageScore);
676
- const serializedAlignmentVerdicts = serializeVerdicts(alignmentVerdicts);
677
- const reasonResult = await maybeReason({
678
- model: options.model,
679
- includeReason: config.includeReason,
680
- retries: config.retries,
681
- metric: "summarization",
682
- score,
683
- evidence: {
684
- alignmentVerdicts: serializedAlignmentVerdicts,
685
- coverageVerdicts,
686
- alignmentScore,
687
- coverageScore
688
- }
689
- });
690
- const usage = addUsage(
691
- truthResult.usage,
692
- claimResult.usage,
693
- questionResult.usage,
694
- sourceAnswerResult.usage,
695
- summaryAnswerResult.usage,
696
- alignmentResult.usage,
697
- reasonResult.usage
698
- );
699
- return higherOutcome({
700
- score,
701
- threshold: config.threshold,
702
- strictMode: config.strictMode,
703
- comment: reasonResult.reason,
704
- details: {
705
- truths,
706
- claims,
707
- assessmentQuestions: questions,
708
- alignmentVerdicts: serializedAlignmentVerdicts,
709
- coverageVerdicts,
710
- scoreBreakdown: { alignment: alignmentScore, coverage: coverageScore }
711
- },
712
- usage
713
- });
714
- } catch (error) {
715
- return EvalOutcome.fromError(error);
716
- }
717
- });
718
- }
719
- function gEval(options) {
720
- if (options.name.trim().length === 0) throw new TypeError("gEval name must not be empty.");
721
- if (options.evaluationParams.length === 0) {
722
- throw new TypeError("gEval requires at least one evaluation parameter.");
723
- }
724
- if (options.criteria === void 0 === (options.evaluationSteps === void 0)) {
725
- throw new TypeError("gEval requires exactly one of criteria or evaluationSteps.");
726
- }
727
- if (options.criteria !== void 0 && options.criteria.trim().length === 0) {
728
- throw new TypeError("gEval criteria must not be empty.");
729
- }
730
- if (options.evaluationSteps !== void 0 && options.evaluationSteps.length === 0) {
731
- throw new TypeError("gEval evaluationSteps must not be empty.");
732
- }
733
- const config = metricConfig(options, options.name);
734
- const rubric = validateRubric(options.rubric);
735
- const scoreRange = rubric.length === 0 ? [0, 10] : [rubric[0]?.scoreRange[0] ?? 0, rubric.at(-1)?.scoreRange[1] ?? 10];
736
- let generatedStepsPromise;
737
- let generatedUsageClaimed = false;
738
- async function resolveSteps() {
739
- if (options.evaluationSteps !== void 0) {
740
- return { steps: options.evaluationSteps, usage: Usage.empty() };
741
- }
742
- if (generatedStepsPromise === void 0) {
743
- generatedStepsPromise = runJudge({
744
- model: options.model,
745
- schema: z.object({ steps: z.array(z.string()) }),
746
- instructions: "Generate three or four concise evaluation steps from the criteria. Explain how the selected parameters should be judged in relation to one another.",
747
- prompt: jsonPrompt({ criteria: options.criteria, parameters: options.evaluationParams }),
748
- retries: config.retries
749
- }).catch((error) => {
750
- generatedStepsPromise = void 0;
751
- throw error;
752
- });
753
- }
754
- const result = await generatedStepsPromise;
755
- if (result.data.steps.length === 0) throw new Error("G-Eval generated no evaluation steps.");
756
- const usage = generatedUsageClaimed ? Usage.empty() : result.usage;
757
- generatedUsageClaimed = true;
758
- return { steps: result.data.steps, usage };
759
- }
760
- return numericMetric(config.name, config, "higher_is_better", async (args) => {
761
- try {
762
- const parameters = await resolveGEvalParameters(options, args);
763
- const stepsResult = await resolveSteps();
764
- const scoreResult = await runJudge({
765
- model: options.model,
766
- schema: z.object({ score: z.number(), reason: z.string() }),
767
- instructions: config.strictMode ? "Apply the evaluation steps and return score 1 only for complete compliance, otherwise 0. Give a concise evidence-based reason." : `Apply the evaluation steps and return an integer score from ${scoreRange[0]} through ${scoreRange[1]}, plus a concise evidence-based reason.`,
768
- prompt: jsonPrompt({
769
- evaluationSteps: stepsResult.steps,
770
- rubric,
771
- parameters
772
- }),
773
- retries: config.retries
774
- });
775
- const rawScore = scoreResult.data.score;
776
- if (!Number.isFinite(rawScore) || config.strictMode && rawScore !== 0 && rawScore !== 1 || !config.strictMode && (rawScore < scoreRange[0] || rawScore > scoreRange[1])) {
777
- throw new RangeError(`G-Eval score ${rawScore} is outside the requested range.`);
778
- }
779
- const score = config.strictMode ? rawScore : (rawScore - scoreRange[0]) / (scoreRange[1] - scoreRange[0]);
780
- const usage = addUsage(stepsResult.usage, scoreResult.usage);
781
- return higherOutcome({
782
- score,
783
- threshold: config.threshold,
784
- strictMode: config.strictMode,
785
- comment: config.includeReason ? scoreResult.data.reason : void 0,
786
- details: {
787
- evaluationSteps: stepsResult.steps,
788
- evaluationParams: options.evaluationParams,
789
- rawScore,
790
- scoreRange: [scoreRange[0], scoreRange[1]],
791
- rubric: rubric.map((entry) => ({
792
- scoreRange: [entry.scoreRange[0], entry.scoreRange[1]],
793
- expectedOutcome: entry.expectedOutcome
794
- }))
795
- },
796
- usage
797
- });
798
- } catch (error) {
799
- return EvalOutcome.fromError(error);
800
- }
801
- });
802
- }
803
- function turnRelevancy(options) {
804
- const config = metricConfig(options, "turn_relevancy");
805
- const windowSize = validatePositiveInteger(options.windowSize ?? 10, "windowSize");
806
- const concurrency = validatePositiveInteger(options.concurrency ?? 4, "concurrency");
807
- return numericMetric(config.name, config, "higher_is_better", async (args) => {
808
- try {
809
- const turns = await resolveTurns(options.turns, args);
810
- const interactions = unitInteractions(turns);
811
- const windows = interactions.map(
812
- (_, index) => interactions.slice(Math.max(0, index - windowSize + 1), index + 1).flat()
813
- );
814
- const verdictResults = await mapWithConcurrency(
815
- windows,
816
- concurrency,
817
- (window) => runJudge({
818
- model: options.model,
819
- schema: binaryVerdictSchema,
820
- instructions: "Judge whether the final assistant reply is relevant to the preceding conversation. Return yes for relevant and no for irrelevant, with a concise reason.",
821
- prompt: jsonPrompt({ turns: window }),
822
- retries: config.retries
823
- })
824
- );
825
- const verdicts = verdictResults.map((result, index) => ({
826
- interaction: index + 1,
827
- ...result.data
828
- }));
829
- const score = verdicts.length === 0 ? 1 : verdicts.filter((verdict) => verdict.verdict === "yes").length / verdicts.length;
830
- const reasonResult = await maybeReason({
831
- model: options.model,
832
- includeReason: config.includeReason,
833
- retries: config.retries,
834
- metric: "turn relevancy",
835
- score,
836
- evidence: { verdicts }
837
- });
838
- const usage = addUsage(...verdictResults.map((result) => result.usage), reasonResult.usage);
839
- return higherOutcome({
840
- score,
841
- threshold: config.threshold,
842
- strictMode: config.strictMode,
843
- comment: reasonResult.reason,
844
- details: { windowSize, concurrency, interactionCount: interactions.length, verdicts },
845
- usage
846
- });
847
- } catch (error) {
848
- return EvalOutcome.fromError(error);
849
- }
850
- });
851
- }
852
- function knowledgeRetention(options) {
853
- const config = metricConfig(options, "knowledge_retention");
854
- const concurrency = validatePositiveInteger(options.concurrency ?? 4, "concurrency");
855
- return numericMetric(config.name, config, "higher_is_better", async (args) => {
856
- try {
857
- const turns = await resolveTurns(options.turns, args);
858
- const userTurns = turns.map((turn, index) => ({ turn, index })).filter((entry) => entry.turn.role === "user");
859
- const knowledgeResults = await mapWithConcurrency(
860
- userTurns,
861
- concurrency,
862
- (entry) => runJudge({
863
- model: options.model,
864
- schema: factsSchema,
865
- instructions: "Extract durable factual information newly supplied by the final user message. Use prior turns only to resolve references. Return concise facts; return an empty array when nothing new was supplied.",
866
- prompt: jsonPrompt({
867
- previousTurns: turns.slice(0, entry.index),
868
- userMessage: entry.turn.content
869
- }),
870
- retries: config.retries
871
- })
872
- );
873
- const knowledge = userTurns.map((entry, index) => ({
874
- turnIndex: entry.index,
875
- facts: knowledgeResults[index]?.data.facts ?? []
876
- }));
877
- const assistantChecks = turns.map((turn, index) => ({ turn, index })).filter((entry) => entry.turn.role === "assistant").map((entry) => ({
878
- ...entry,
879
- facts: knowledge.filter((item) => item.turnIndex < entry.index).flatMap((item) => item.facts)
880
- })).filter((entry) => entry.facts.length > 0);
881
- const verdictResults = await mapWithConcurrency(
882
- assistantChecks,
883
- concurrency,
884
- (entry) => runJudge({
885
- model: options.model,
886
- schema: z.object({ attrition: z.boolean(), reason: z.string() }),
887
- instructions: "Determine whether the assistant reply forgets, contradicts, or unnecessarily asks again for information already supplied by the user. Set attrition true only when knowledge was lost.",
888
- prompt: jsonPrompt({ knownFacts: entry.facts, assistantReply: entry.turn.content }),
889
- retries: config.retries
890
- })
891
- );
892
- const verdicts = assistantChecks.map((entry, index) => ({
893
- turnIndex: entry.index,
894
- attrition: verdictResults[index]?.data.attrition ?? true,
895
- reason: verdictResults[index]?.data.reason ?? "Missing knowledge-retention verdict."
896
- }));
897
- const score = verdicts.length === 0 ? 1 : verdicts.filter((verdict) => !verdict.attrition).length / verdicts.length;
898
- const reasonResult = await maybeReason({
899
- model: options.model,
900
- includeReason: config.includeReason,
901
- retries: config.retries,
902
- metric: "knowledge retention",
903
- score,
904
- evidence: { verdicts }
905
- });
906
- const usage = addUsage(
907
- ...knowledgeResults.map((result) => result.usage),
908
- ...verdictResults.map((result) => result.usage),
909
- reasonResult.usage
910
- );
911
- return higherOutcome({
912
- score,
913
- threshold: config.threshold,
914
- strictMode: config.strictMode,
915
- comment: reasonResult.reason,
916
- details: { concurrency, knowledge, verdicts },
917
- usage
918
- });
919
- } catch (error) {
920
- return EvalOutcome.fromError(error);
921
- }
922
- });
923
- }
924
- function numericMetric(name, config, direction, evaluate) {
925
- return {
926
- name,
927
- required: config.required,
928
- direction,
929
- threshold: config.strictMode === true ? direction === "higher_is_better" ? 1 : 0 : config.threshold,
930
- dataType: "NUMERIC",
931
- evaluate
932
- };
933
- }
934
- function metricConfig(options, defaultName) {
935
- return {
936
- name: options.name ?? defaultName,
937
- threshold: validateThreshold(options.threshold ?? 0.5),
938
- strictMode: options.strictMode ?? false,
939
- includeReason: options.includeReason ?? true,
940
- retries: validateRetries(options.retries ?? 0),
941
- required: options.required ?? true
942
- };
943
- }
944
- function higherOutcome(args) {
945
- const score = args.strictMode ? args.score === 1 ? 1 : 0 : args.score;
946
- const threshold = args.strictMode ? 1 : args.threshold;
947
- const options = {
948
- comment: args.comment,
949
- usage: args.usage,
950
- metadata: evaluationMetadata(
951
- {
952
- ...args.details,
953
- scoreDirection: "higher_is_better",
954
- threshold,
955
- strictMode: args.strictMode
956
- },
957
- args.usage
958
- )
959
- };
960
- return score >= threshold ? EvalOutcome.pass(score, options) : EvalOutcome.fail(score, options);
961
- }
962
- function lowerOutcome(args) {
963
- const score = args.strictMode ? args.score === 0 ? 0 : 1 : args.score;
964
- const threshold = args.strictMode ? 0 : args.threshold;
965
- const options = {
966
- comment: args.comment,
967
- usage: args.usage,
968
- metadata: evaluationMetadata(
969
- {
970
- ...args.details,
971
- scoreDirection: "lower_is_better",
972
- threshold,
973
- strictMode: args.strictMode
974
- },
975
- args.usage
976
- )
977
- };
978
- return score <= threshold ? EvalOutcome.pass(score, options) : EvalOutcome.fail(score, options);
979
- }
980
- async function maybeReason(args) {
981
- if (!args.includeReason) return { usage: Usage.empty() };
982
- const result = await runJudge({
983
- model: args.model,
984
- schema: reasonSchema,
985
- instructions: `Write a concise final explanation for the ${args.metric} score. Ground it only in the supplied evidence and do not repeat the numeric score.`,
986
- prompt: jsonPrompt({ score: args.score, evidence: args.evidence }),
987
- retries: args.retries
988
- });
989
- return { reason: result.data.reason, usage: result.usage };
990
- }
991
- async function resolveInput(selector, args) {
992
- return selector === void 0 ? formatValue(args.case.input) : selector(args);
993
- }
994
- async function resolveStringList(selectorOrValue, fallback, args, label) {
995
- const value = selectorOrValue === void 0 ? fallback : typeof selectorOrValue === "function" ? await selectorOrValue(args) : selectorOrValue;
996
- if (!Array.isArray(value) || value.length === 0 || value.some((item) => typeof item !== "string")) {
997
- throw new TypeError(`${label} must be a non-empty array of strings.`);
998
- }
999
- return value;
1000
- }
1001
- async function resolveGEvalParameters(options, args) {
1002
- const parameters = {};
1003
- for (const parameter of options.evaluationParams) {
1004
- if (parameter === "input") parameters.input = await resolveInput(options.input, args);
1005
- if (parameter === "actualOutput") {
1006
- parameters.actualOutput = await resolveActualText(options.actual, args);
1007
- }
1008
- if (parameter === "expectedOutput") {
1009
- const expected = options.expected === void 0 ? args.case.expected : await options.expected(args);
1010
- if (expected === void 0) throw new Error("G-Eval expectedOutput is missing.");
1011
- parameters.expectedOutput = toJsonValue(expected);
1012
- }
1013
- if (parameter === "context") {
1014
- parameters.context = await resolveStringList(
1015
- options.context,
1016
- args.case.context,
1017
- args,
1018
- "context"
1019
- );
1020
- }
1021
- if (parameter === "retrievalContext") {
1022
- parameters.retrievalContext = await resolveStringList(
1023
- options.retrievalContext,
1024
- args.case.retrievalContext,
1025
- args,
1026
- "retrievalContext"
1027
- );
1028
- }
1029
- if (parameter === "metadata") parameters.metadata = args.case.metadata ?? {};
1030
- }
1031
- return parameters;
1032
- }
1033
- function validateRubric(rubric) {
1034
- if (rubric === void 0 || rubric.length === 0) return [];
1035
- const sorted = [...rubric].sort((left, right) => left.scoreRange[0] - right.scoreRange[0]);
1036
- for (const [index, entry] of sorted.entries()) {
1037
- const [start, end] = entry.scoreRange;
1038
- if (!Number.isInteger(start) || !Number.isInteger(end) || start < 0 || end > 10 || start > end) {
1039
- throw new RangeError(
1040
- "G-Eval rubric score ranges must be ordered integers from 0 through 10."
1041
- );
1042
- }
1043
- if (entry.expectedOutcome.trim().length === 0) {
1044
- throw new TypeError("G-Eval rubric expectedOutcome must not be empty.");
1045
- }
1046
- const next = sorted[index + 1];
1047
- if (next !== void 0 && end >= next.scoreRange[0]) {
1048
- throw new RangeError("G-Eval rubric score ranges must not overlap.");
1049
- }
1050
- }
1051
- const first = sorted[0];
1052
- const last = sorted.at(-1);
1053
- if (first !== void 0 && last !== void 0 && first.scoreRange[0] === last.scoreRange[1]) {
1054
- throw new RangeError("G-Eval rubric score range must span more than one value.");
1055
- }
1056
- return sorted;
1057
- }
1058
- function truthsExtractionInstructions(limit) {
1059
- return limit === void 0 ? "Extract concise, factual, undisputed truths from the supplied source material, ordered by importance. Return them in the facts array." : `Extract at most ${limit} concise, factual, undisputed truths from the supplied source material, ordered by importance. Return them in the facts array.`;
1060
- }
1061
- function limitValues(values, limit) {
1062
- return limit === void 0 ? values : values.slice(0, limit);
1063
- }
1064
- function validateThreshold(value) {
1065
- if (!Number.isFinite(value) || value < 0 || value > 1) {
1066
- throw new RangeError("Eval metric threshold must be between 0 and 1.");
1067
- }
1068
- return value;
1069
- }
1070
- function validateRetries(value) {
1071
- if (!Number.isInteger(value) || value < 0) {
1072
- throw new RangeError("Eval metric retries must be a non-negative integer.");
1073
- }
1074
- return value;
1075
- }
1076
- function validatePositiveInteger(value, label) {
1077
- if (!Number.isInteger(value) || value < 1) {
1078
- throw new RangeError(`${label} must be a positive integer.`);
1079
- }
1080
- return value;
1081
- }
1082
- function validateOptionalNonNegativeInteger(value, label) {
1083
- if (value === void 0) return void 0;
1084
- if (!Number.isInteger(value) || value < 0) {
1085
- throw new RangeError(`${label} must be a non-negative integer.`);
1086
- }
1087
- return value;
1088
- }
1089
- function assertSameLength(label, inputs, outputs) {
1090
- if (inputs.length !== outputs.length) {
1091
- throw new Error(`${label} count ${outputs.length} did not match input count ${inputs.length}.`);
1092
- }
1093
- }
1094
- function serializeVerdicts(verdicts) {
1095
- return verdicts.map((verdict) => {
1096
- const serialized = { verdict: verdict.verdict };
1097
- if (verdict.reason !== void 0) serialized.reason = verdict.reason;
1098
- return serialized;
1099
- });
1100
- }
1101
- function jsonPrompt(value) {
1102
- return JSON.stringify(value, null, 2);
1103
- }
1104
- function toJsonValue(value) {
1105
- if (!isJsonValue(value)) {
1106
- throw new TypeError("G-Eval expectedOutput must be a JSON value.");
1107
- }
1108
- return cloneJsonValue(value);
1109
- }
1110
- function cloneJsonValue(value) {
1111
- if (value === null || typeof value !== "object") return value;
1112
- if (Array.isArray(value)) return value.map(cloneJsonValue);
1113
- return Object.fromEntries(
1114
- Object.entries(value).map(([key, item]) => {
1115
- if (item === void 0) {
1116
- throw new TypeError("G-Eval expectedOutput must be a JSON value.");
1117
- }
1118
- return [key, cloneJsonValue(item)];
1119
- })
1120
- );
1121
- }
1122
- function normalizeEvalTurns(value) {
1123
- const source = conversationArray(value);
1124
- if (source === void 0) return void 0;
1125
- const turns = [];
1126
- for (const entry of source) {
1127
- if (typeof entry !== "object" || entry === null) continue;
1128
- const role = entry.role;
1129
- if (role !== "user" && role !== "assistant") continue;
1130
- const content = entry.content;
1131
- const text = contentText(content);
1132
- if (text.length === 0) continue;
1133
- const metadata = entry.metadata;
1134
- turns.push(
1135
- typeof metadata === "object" && metadata !== null && !Array.isArray(metadata) ? { role, content: text, metadata } : { role, content: text }
1136
- );
1137
- }
1138
- return turns.length === 0 ? void 0 : turns;
1139
- }
1140
- async function resolveTurns(selector, args) {
1141
- const source = selector === void 0 ? args.output : await selector(args);
1142
- const turns = normalizeEvalTurns(source);
1143
- if (turns === void 0) {
1144
- throw new TypeError(
1145
- "Conversational eval requires non-empty EvalTurn[], Message[], or an output with messages."
1146
- );
1147
- }
1148
- return turns;
1149
- }
1150
- function unitInteractions(turns) {
1151
- const interactions = [];
1152
- let current = [];
1153
- let hasUser = false;
1154
- for (const turn of turns) {
1155
- if (current.at(-1)?.role === "assistant" && turn.role === "user" && hasUser) {
1156
- interactions.push(current);
1157
- current = [turn];
1158
- hasUser = true;
1159
- continue;
1160
- }
1161
- current.push(turn);
1162
- if (turn.role === "user") hasUser = true;
1163
- }
1164
- if (current.length > 1 && current.at(-1)?.role === "assistant" && hasUser) {
1165
- interactions.push(current);
1166
- }
1167
- return interactions;
1168
- }
1169
- function conversationArray(value) {
1170
- if (Array.isArray(value)) return value;
1171
- if (typeof value === "object" && value !== null && "messages" in value) {
1172
- const messages = value.messages;
1173
- return Array.isArray(messages) ? messages : void 0;
1174
- }
1175
- return void 0;
1176
- }
1177
- function contentText(content) {
1178
- if (typeof content === "string") return content;
1179
- if (!Array.isArray(content)) return "";
1180
- return content.flatMap(
1181
- (part) => typeof part === "object" && part !== null && "type" in part && part.type === "text" && "text" in part && typeof part.text === "string" ? [part.text] : []
1182
- ).join("\n");
1183
- }
1184
-
1185
- // src/evals/agent-target.ts
1186
- var AgentEvalSuspensionError = class extends Error {
1187
- constructor(result, message = "Agent eval target suspended without an interaction responder.") {
1188
- super(message);
1189
- this.result = result;
1190
- this.name = "AgentEvalSuspensionError";
1191
- }
1192
- result;
1193
- };
1194
- function agentEvalTarget(options) {
1195
- return async (input, testCase) => {
1196
- const maxResponses = options.interactions?.maxResponses ?? 10;
1197
- if (!Number.isSafeInteger(maxResponses) || maxResponses < 1) {
1198
- throw new TypeError("Agent eval interactions.maxResponses must be a positive integer.");
1199
- }
1200
- const request = await options.request({ input, testCase });
1201
- const runSettings = agentRunSettings(request);
1202
- let response = await options.agent.generate(request);
1203
- let phase = 0;
1204
- while (response.type === "interaction") {
1205
- if (options.interactions === void 0) {
1206
- throw new AgentEvalSuspensionError(response);
1207
- }
1208
- if (phase >= maxResponses) {
1209
- throw new AgentEvalSuspensionError(
1210
- response,
1211
- `Agent eval target exceeded the interaction response limit of ${maxResponses}.`
1212
- );
1213
- }
1214
- phase += 1;
1215
- const interactionResponse = await options.interactions.respond({
1216
- interaction: response.interaction,
1217
- testCase,
1218
- phase
1219
- });
1220
- response = await options.agent.generate({
1221
- continuation: response.continuation,
1222
- response: interactionResponse,
1223
- ...runSettings
1224
- });
1225
- }
1226
- if (response.type === "blocked") throw new AgentRunBlockedError(response);
1227
- return options.output === void 0 ? response : await options.output({ response, testCase });
1228
- };
1229
- }
1230
- function agentRunSettings(request) {
1231
- const {
1232
- prompt: _prompt,
1233
- messages: _messages,
1234
- session: _session,
1235
- continuation: _continuation,
1236
- response: _response,
1237
- ...settings
1238
- } = request;
1239
- return settings;
1240
- }
1241
-
1242
- // src/evals/execution.ts
1243
- var EvalTimeoutError = class extends Error {
1244
- constructor(timeoutMs) {
1245
- super(`Evaluation case exceeded its timeout of ${timeoutMs}ms.`);
1246
- this.timeoutMs = timeoutMs;
1247
- this.name = "EvalTimeoutError";
1248
- }
1249
- timeoutMs;
1250
- };
1251
- var EvalAbortError = class extends Error {
1252
- constructor(message = "Evaluation run was aborted.") {
1253
- super(message);
1254
- this.name = "EvalAbortError";
1255
- }
1256
- };
1257
- function createEvalCaseSignal(parent, timeoutMs) {
1258
- const controller = new AbortController();
1259
- const abortFromParent = () => controller.abort(parent?.reason ?? new EvalAbortError());
1260
- if (parent?.aborted === true) abortFromParent();
1261
- else parent?.addEventListener("abort", abortFromParent, { once: true });
1262
- const timeout = timeoutMs === void 0 ? void 0 : setTimeout(() => controller.abort(new EvalTimeoutError(timeoutMs)), timeoutMs);
1263
- return {
1264
- signal: controller.signal,
1265
- dispose() {
1266
- if (timeout !== void 0) clearTimeout(timeout);
1267
- parent?.removeEventListener("abort", abortFromParent);
1268
- }
1269
- };
1270
- }
1271
- function abortable(signal, operation) {
1272
- if (signal.aborted) return Promise.reject(abortReason(signal));
1273
- return new Promise((resolve, reject) => {
1274
- const onAbort = () => reject(abortReason(signal));
1275
- signal.addEventListener("abort", onAbort, { once: true });
1276
- operation.then(
1277
- (value) => {
1278
- signal.removeEventListener("abort", onAbort);
1279
- resolve(value);
1280
- },
1281
- (error) => {
1282
- signal.removeEventListener("abort", onAbort);
1283
- reject(error);
1284
- }
1285
- );
1286
- });
1287
- }
1288
- function createConcurrencyLimiter(concurrency) {
1289
- let active = 0;
1290
- const waiting = [];
1291
- return async (operation) => {
1292
- if (active >= concurrency) {
1293
- await new Promise((resolve) => waiting.push(resolve));
1294
- }
1295
- active += 1;
1296
- try {
1297
- return await operation();
1298
- } finally {
1299
- active -= 1;
1300
- waiting.shift()?.();
1301
- }
1302
- };
1303
- }
1304
- function abortReason(signal) {
1305
- return signal.reason ?? new EvalAbortError();
1306
- }
1307
-
1308
- // src/evals/reporting.ts
1309
- function projectEvalOutcome(outcome, dataType, projectScore) {
1310
- const value = projectScoreValue(outcome, dataType, projectScore);
1311
- const projection = {
1312
- outcome: outcome.outcome,
1313
- value,
1314
- label: typeof value === "string" ? value : outcome.outcome
1315
- };
1316
- if (typeof value === "number") projection.numericValue = value;
1317
- if (typeof value === "string") projection.categoricalValue = value;
1318
- const explanation = outcome.comment ?? (outcome.outcome === "invalid" ? outcome.reason : void 0);
1319
- if (explanation !== void 0) projection.explanation = explanation;
1320
- return projection;
1321
- }
1322
- function resolveEvalTraceRef(args) {
1323
- return traceFromCarrier(args.output) ?? traceFromCarrier(args.input) ?? traceFromMetadata(args.metadata);
1324
- }
1325
- function defaultEvalTraceSelector(args) {
1326
- return resolveEvalTraceRef({
1327
- output: args.output,
1328
- input: args.case.input,
1329
- metadata: args.case.metadata
1330
- });
1331
- }
1332
- function projectScoreValue(outcome, dataType, projectScore) {
1333
- const score = outcome.score;
1334
- if (score !== void 0 && projectScore !== void 0) {
1335
- const projected = projectScore(score);
1336
- if (typeof projected === "boolean") return projected ? 1 : 0;
1337
- return projected;
1338
- }
1339
- if (dataType === "CATEGORICAL") {
1340
- if (typeof score === "string") return score;
1341
- if (typeof score === "number") return String(score);
1342
- if (typeof score === "boolean") return score ? "true" : "false";
1343
- if (score === null || score === void 0) return outcome.outcome;
1344
- try {
1345
- return JSON.stringify(score) ?? outcome.outcome;
1346
- } catch {
1347
- return outcome.outcome;
1348
- }
1349
- }
1350
- if (dataType === "BOOLEAN") {
1351
- if (typeof score === "boolean") return score ? 1 : 0;
1352
- if (typeof score === "number") return score === 0 ? 0 : 1;
1353
- return outcome.outcome === "pass" ? 1 : 0;
1354
- }
1355
- if (typeof score === "number") return score;
1356
- if (typeof score === "boolean") return score ? 1 : 0;
1357
- if (typeof score === "object" && score !== null && "score" in score && typeof score.score === "number") {
1358
- return score.score;
1359
- }
1360
- return outcome.outcome === "pass" ? 1 : 0;
1361
- }
1362
- function traceFromCarrier(value) {
1363
- if (typeof value !== "object" || value === null || !("trace" in value)) return void 0;
1364
- return readTraceRef(value.trace);
1365
- }
1366
- function traceFromMetadata(metadata) {
1367
- if (metadata === void 0) return void 0;
1368
- return readTraceRef({
1369
- observer: metadata.traceObserver,
1370
- traceId: metadata.traceId,
1371
- observationId: metadata.observationId,
1372
- responseId: metadata.responseId
1373
- });
1374
- }
1375
- function readTraceRef(value) {
1376
- if (typeof value !== "object" || value === null) return void 0;
1377
- const traceId = value.traceId;
1378
- if (typeof traceId !== "string" || traceId.length === 0) return void 0;
1379
- const observer = value.observer;
1380
- const observationId = value.observationId;
1381
- const responseId = value.responseId;
1382
- const trace = { traceId };
1383
- if (typeof observer === "string" && observer.length > 0) trace.observer = observer;
1384
- if (typeof observationId === "string" && observationId.length > 0) {
1385
- trace.observationId = observationId;
1386
- }
1387
- if (typeof responseId === "string" && responseId.length > 0) trace.responseId = responseId;
1388
- return trace;
1389
- }
1390
-
1391
- // src/evals/runner.ts
1392
- var EvalReporterDispatchError = class extends AggregateError {
1393
- phase;
1394
- constructor(phase, errors) {
1395
- super(errors, `Evaluation reporter ${phase} failed ${errors.length} time(s).`);
1396
- this.name = "EvalReporterDispatchError";
1397
- this.phase = phase;
1398
- }
1399
- };
1400
- var EvalFailFastError = class extends Error {
1401
- constructor(caseId, outcome) {
1402
- super(`Evaluation stopped after case ${caseId} produced a required ${outcome} outcome.`);
1403
- this.caseId = caseId;
1404
- this.outcome = outcome;
1405
- this.name = "EvalFailFastError";
1406
- }
1407
- caseId;
1408
- outcome;
1409
- };
1410
- async function runEvalSuite(options) {
1411
- validateSuiteOptions(options);
1412
- const selectedCases = selectCases(options);
1413
- const selectedOptions = {
1414
- ...options,
1415
- cases: selectedCases
1416
- };
1417
- const startedAtMs = Date.now();
1418
- const run = resolveRun(selectedOptions, startedAtMs);
1419
- const reporters = options.reporters ?? [];
1420
- const lifecycle = {
1421
- run,
1422
- suiteName: options.name,
1423
- caseCount: selectedCases.length,
1424
- metricNames: options.metrics.map((metric) => metric.name)
1425
- };
1426
- let reporterErrors;
1427
- try {
1428
- reporterErrors = await notifyRunStart(
1429
- reporters,
1430
- lifecycle,
1431
- options.reporterErrorPolicy ?? "collect"
1432
- );
1433
- } catch (error) {
1434
- await notifyRunEnd(reporters, {
1435
- ...lifecycle,
1436
- status: "failed",
1437
- completedAt: (/* @__PURE__ */ new Date()).toISOString(),
1438
- durationMs: Date.now() - startedAtMs,
1439
- error
1440
- });
1441
- throw error;
1442
- }
1443
- let results;
1444
- let aggregates;
1445
- try {
1446
- results = await runEvalCases(selectedOptions, run);
1447
- aggregates = await aggregateResult(selectedOptions, results);
1448
- } catch (error) {
1449
- await notifyRunEnd(reporters, {
1450
- ...lifecycle,
1451
- status: "failed",
1452
- completedAt: (/* @__PURE__ */ new Date()).toISOString(),
1453
- durationMs: Date.now() - startedAtMs,
1454
- error
1455
- });
1456
- throw error;
1457
- }
1458
- const completedAt = (/* @__PURE__ */ new Date()).toISOString();
1459
- const result = {
1460
- name: options.name,
1461
- run: { ...run, completedAt },
1462
- results,
1463
- metrics: aggregates.metrics,
1464
- cases: aggregates.cases,
1465
- usage: aggregates.usage,
1466
- durationMs: Date.now() - startedAtMs,
1467
- reporterErrors
1468
- };
1469
- result.reporterErrors.push(
1470
- ...results.flatMap(
1471
- (caseResult) => caseResult.metrics.flatMap((metricResult) => metricResult.reporterErrors)
1472
- )
1473
- );
1474
- if (aggregates.cost !== void 0) {
1475
- result.cost = aggregates.cost;
1476
- }
1477
- const runEndArgs = {
1478
- ...lifecycle,
1479
- status: "completed",
1480
- completedAt,
1481
- durationMs: result.durationMs,
1482
- metrics: result.metrics,
1483
- cases: result.cases,
1484
- usage: result.usage
1485
- };
1486
- if (result.cost !== void 0) {
1487
- runEndArgs.cost = result.cost;
1488
- }
1489
- result.reporterErrors.push(
1490
- ...await notifyRunEnd(reporters, runEndArgs, options.reporterErrorPolicy ?? "collect")
1491
- );
1492
- return result;
1493
- }
1494
- async function runEvalCases(options, run) {
1495
- const targetConcurrency = options.targetConcurrency ?? options.concurrency ?? 1;
1496
- const metricConcurrency = options.metricConcurrency ?? options.concurrency ?? 1;
1497
- const workerConcurrency = Math.max(targetConcurrency, metricConcurrency);
1498
- const targetLimit = createConcurrencyLimiter(targetConcurrency);
1499
- const metricLimit = createConcurrencyLimiter(metricConcurrency);
1500
- const results = Array(options.cases.length);
1501
- let nextIndex = 0;
1502
- let completedCases = 0;
1503
- let failure;
1504
- async function worker() {
1505
- while (failure === void 0 && nextIndex < options.cases.length) {
1506
- if (isAborted(options.signal)) {
1507
- failure ??= { error: suiteAbortReason(options.signal) };
1508
- break;
1509
- }
1510
- const index = nextIndex;
1511
- nextIndex += 1;
1512
- try {
1513
- results[index] = await runEvalCase(
1514
- options,
1515
- options.cases[index],
1516
- run,
1517
- targetLimit,
1518
- metricLimit,
1519
- () => completedCases
1520
- );
1521
- completedCases += 1;
1522
- if (isAborted(options.signal)) {
1523
- failure ??= { error: suiteAbortReason(options.signal) };
1524
- }
1525
- if (options.failFast === true && results[index]?.outcome !== "pass") {
1526
- const result = results[index];
1527
- if (result !== void 0 && result.outcome !== "pass") {
1528
- failure ??= { error: new EvalFailFastError(result.case.id, result.outcome) };
1529
- }
1530
- }
1531
- } catch (error) {
1532
- failure ??= { error };
1533
- }
1534
- }
1535
- }
1536
- await Promise.all(
1537
- Array.from({ length: Math.min(workerConcurrency, options.cases.length) }, () => worker())
1538
- );
1539
- if (failure !== void 0) throw failure.error;
1540
- return results;
1541
- }
1542
- async function runEvalCase(options, testCase, run, targetLimit, metricLimit, completedCases) {
1543
- const caseStartedAt = performance.now();
1544
- const caseSignal = createEvalCaseSignal(options.signal, options.caseTimeoutMs);
1545
- try {
1546
- const progress = (event) => notifyProgress(options, event);
1547
- await progress({
1548
- type: "case-start",
1549
- suiteName: options.name,
1550
- case: testCase,
1551
- completedCases: completedCases(),
1552
- totalCases: options.cases.length
1553
- });
1554
- let output;
1555
- let targetError;
1556
- let targetStatus = "succeeded";
1557
- let targetDurationMs = 0;
1558
- try {
1559
- output = await targetLimit(async () => {
1560
- const targetStartedAt = performance.now();
1561
- try {
1562
- return await (caseSignal.signal.aborted ? Promise.reject(caseSignal.signal.reason) : abortable(
1563
- caseSignal.signal,
1564
- Promise.resolve(
1565
- options.target(testCase.input, testCase, { signal: caseSignal.signal })
1566
- )
1567
- ));
1568
- } finally {
1569
- targetDurationMs = performance.now() - targetStartedAt;
1570
- }
1571
- });
1572
- } catch (error) {
1573
- if (options.signal?.aborted === true) {
1574
- throw options.signal.reason ?? new EvalAbortError();
1575
- }
1576
- targetStatus = "failed";
1577
- targetError = error;
1578
- }
1579
- await progress({
1580
- type: "target-complete",
1581
- suiteName: options.name,
1582
- case: testCase,
1583
- targetStatus,
1584
- output,
1585
- error: targetError,
1586
- durationMs: targetDurationMs,
1587
- completedCases: completedCases(),
1588
- totalCases: options.cases.length
1589
- });
1590
- const traceResult = await resolveTrace(options, testCase, output, targetError, targetStatus);
1591
- const metrics = await Promise.all(
1592
- options.metrics.map(
1593
- (metric) => metricLimit(async () => {
1594
- const metricStartedAt = performance.now();
1595
- const outcome = targetStatus === "succeeded" ? await safeEvaluate(
1596
- options.name,
1597
- testCase,
1598
- output,
1599
- metric,
1600
- caseSignal.signal
1601
- ) : EvalOutcome.invalid(`Target failed: ${errorMessage(targetError)}`, {
1602
- kind: targetError instanceof EvalTimeoutError ? "timeout" : "target",
1603
- error: targetError
1604
- });
1605
- const durationMs = performance.now() - metricStartedAt;
1606
- const reporterErrors = await reportOutcome({
1607
- run,
1608
- suiteName: options.name,
1609
- testCase,
1610
- output,
1611
- targetError,
1612
- targetStatus,
1613
- metric,
1614
- outcome,
1615
- trace: traceResult.trace,
1616
- traceError: traceResult.error,
1617
- reporters: options.reporters ?? [],
1618
- reporterErrorPolicy: options.reporterErrorPolicy ?? "collect"
1619
- });
1620
- await progress({
1621
- type: "metric-complete",
1622
- suiteName: options.name,
1623
- case: testCase,
1624
- metricName: metric.name,
1625
- outcome,
1626
- durationMs,
1627
- completedCases: completedCases(),
1628
- totalCases: options.cases.length
1629
- });
1630
- const metricResult = {
1631
- metricName: metric.name,
1632
- required: metric.required ?? true,
1633
- outcome,
1634
- durationMs,
1635
- reporterErrors
1636
- };
1637
- if (metric.direction !== void 0) metricResult.direction = metric.direction;
1638
- if (metric.threshold !== void 0) metricResult.threshold = metric.threshold;
1639
- return metricResult;
1640
- })
1641
- )
1642
- );
1643
- const scores = Object.fromEntries(
1644
- metrics.map((metric) => [metric.metricName, metric.outcome])
1645
- );
1646
- const result = {
1647
- case: testCase,
1648
- outcome: caseOutcome(targetStatus, metrics),
1649
- targetStatus,
1650
- targetDurationMs,
1651
- durationMs: performance.now() - caseStartedAt,
1652
- metrics,
1653
- scores,
1654
- usage: emptyUsageSummary()
1655
- };
1656
- if (targetStatus === "succeeded") {
1657
- result.output = output;
1658
- }
1659
- if (targetStatus === "failed") {
1660
- result.targetError = targetError;
1661
- }
1662
- await progress({
1663
- type: "case-complete",
1664
- suiteName: options.name,
1665
- result,
1666
- completedCases: completedCases() + 1,
1667
- totalCases: options.cases.length
1668
- });
1669
- return result;
1670
- } finally {
1671
- caseSignal.dispose();
1672
- }
1673
- }
1674
- async function resolveTrace(options, testCase, output, targetError, targetStatus) {
1675
- try {
1676
- const selector = options.trace ?? defaultEvalTraceSelector;
1677
- const trace = await selector({
1678
- suiteName: options.name,
1679
- case: testCase,
1680
- output,
1681
- targetError,
1682
- targetStatus
1683
- });
1684
- return trace === void 0 ? {} : { trace };
1685
- } catch (error) {
1686
- return { error };
1687
- }
1688
- }
1689
- async function safeEvaluate(suiteName, testCase, output, metric, signal) {
1690
- if (signal.aborted) {
1691
- return EvalOutcome.fromError(
1692
- signal.reason,
1693
- signal.reason instanceof EvalTimeoutError ? "timeout" : "metric"
1694
- );
1695
- }
1696
- try {
1697
- return await abortable(
1698
- signal,
1699
- Promise.resolve(metric.evaluate({ suiteName, case: testCase, output, signal }))
1700
- );
1701
- } catch (error) {
1702
- return EvalOutcome.fromError(error, error instanceof EvalTimeoutError ? "timeout" : "metric");
1703
- }
1704
- }
1705
- async function reportOutcome(args) {
1706
- const errors = [];
1707
- if (args.traceError !== void 0) {
1708
- errors.push(args.traceError);
1709
- }
1710
- for (const reporter of args.reporters) {
1711
- try {
1712
- await reporter.report({
1713
- run: args.run,
1714
- suiteName: args.suiteName,
1715
- case: args.testCase,
1716
- output: args.output,
1717
- targetError: args.targetError,
1718
- targetStatus: args.targetStatus,
1719
- trace: args.trace,
1720
- metric: args.metric,
1721
- outcome: args.outcome
1722
- });
1723
- } catch (error) {
1724
- errors.push(error);
1725
- }
1726
- }
1727
- throwReporterErrors("report", errors, args.reporterErrorPolicy);
1728
- return errors;
1729
- }
1730
- function resolveRun(options, startedAtMs) {
1731
- const id = options.run?.id ?? globalThis.crypto.randomUUID();
1732
- if (id.trim().length === 0 || id.length > 128) {
1733
- throw new TypeError("Evaluation run id must contain 1 to 128 characters");
1734
- }
1735
- for (const [label, value] of [
1736
- ["dataset name", options.run?.datasetName],
1737
- ["dataset version", options.run?.datasetVersion]
1738
- ]) {
1739
- if (value !== void 0 && (value.trim().length === 0 || value.length > 256)) {
1740
- throw new TypeError(`Evaluation run ${label} must contain 1 to 256 characters`);
1741
- }
1742
- }
1743
- const run = {
1744
- id,
1745
- startedAt: new Date(startedAtMs).toISOString()
1746
- };
1747
- if (options.run?.datasetName !== void 0) run.datasetName = options.run.datasetName;
1748
- if (options.run?.datasetVersion !== void 0) run.datasetVersion = options.run.datasetVersion;
1749
- if (options.run?.metadata !== void 0) run.metadata = options.run.metadata;
1750
- return run;
1751
- }
1752
- async function notifyRunStart(reporters, args, errorPolicy) {
1753
- const errors = [];
1754
- for (const reporter of reporters) {
1755
- if (reporter.onRunStart === void 0) continue;
1756
- try {
1757
- await reporter.onRunStart(args);
1758
- } catch (error) {
1759
- errors.push(error);
1760
- }
1761
- }
1762
- throwReporterErrors("onRunStart", errors, errorPolicy);
1763
- return errors;
1764
- }
1765
- async function notifyRunEnd(reporters, args, errorPolicy = "collect") {
1766
- const errors = [];
1767
- for (const reporter of reporters) {
1768
- if (reporter.onRunEnd === void 0) continue;
1769
- try {
1770
- await reporter.onRunEnd(args);
1771
- } catch (error) {
1772
- errors.push(error);
1773
- }
1774
- }
1775
- throwReporterErrors("onRunEnd", errors, errorPolicy);
1776
- return errors;
1777
- }
1778
- function throwReporterErrors(phase, errors, errorPolicy) {
1779
- if (errorPolicy === "throw" && errors.length > 0) {
1780
- throw new EvalReporterDispatchError(phase, errors);
1781
- }
1782
- }
1783
- function countMetricOutcomes(results) {
1784
- const totals = emptyTotals();
1785
- for (const result of results) {
1786
- for (const metric of result.metrics) {
1787
- totals.total += 1;
1788
- totals[statusKey(metric.outcome.outcome)] += 1;
1789
- }
1790
- }
1791
- return totals;
1792
- }
1793
- function countCaseOutcomes(results) {
1794
- const totals = emptyTotals();
1795
- for (const result of results) {
1796
- totals.total += 1;
1797
- totals[statusKey(result.outcome)] += 1;
1798
- }
1799
- return totals;
1800
- }
1801
- function emptyTotals() {
1802
- return { total: 0, passed: 0, failed: 0, invalid: 0 };
1803
- }
1804
- function emptyUsageSummary() {
1805
- return {
1806
- target: Usage.empty(),
1807
- evaluation: Usage.empty(),
1808
- total: Usage.empty()
1809
- };
1810
- }
1811
- function statusKey(status) {
1812
- if (status === "pass") return "passed";
1813
- if (status === "fail") return "failed";
1814
- return "invalid";
1815
- }
1816
- function caseOutcome(targetStatus, metrics) {
1817
- if (targetStatus === "failed") return "invalid";
1818
- const required = metrics.filter((metric) => metric.required);
1819
- if (required.some((metric) => metric.outcome.outcome === "invalid")) return "invalid";
1820
- if (required.some((metric) => metric.outcome.outcome === "fail")) return "fail";
1821
- return "pass";
1822
- }
1823
- async function aggregateResult(options, results) {
1824
- let targetUsage = Usage.empty();
1825
- let evaluationUsage = Usage.empty();
1826
- let targetCost = 0;
1827
- let evaluationCost = 0;
1828
- for (const result of results) {
1829
- let caseTargetUsage = Usage.empty();
1830
- let caseEvaluationUsage = Usage.empty();
1831
- let caseTargetCost = 0;
1832
- let caseEvaluationCost = 0;
1833
- if (result.targetStatus === "succeeded") {
1834
- const usage2 = await resolveTargetUsage(options, result.case, result.output);
1835
- if (usage2 !== void 0) {
1836
- caseTargetUsage = usage2;
1837
- targetUsage = Usage.add(targetUsage, usage2);
1838
- if (options.cost !== void 0) {
1839
- caseTargetCost = await calculateCost(
1840
- options.cost.calculate({
1841
- kind: "target",
1842
- suiteName: options.name,
1843
- case: result.case,
1844
- output: result.output,
1845
- usage: usage2
1846
- })
1847
- );
1848
- targetCost += caseTargetCost;
1849
- }
1850
- }
1851
- }
1852
- for (const metricResult of result.metrics) {
1853
- const usage2 = metricResult.outcome.usage;
1854
- if (usage2 === void 0) continue;
1855
- assertUsage(usage2, `Evaluation usage for metric ${metricResult.metricName}`);
1856
- caseEvaluationUsage = Usage.add(caseEvaluationUsage, usage2);
1857
- evaluationUsage = Usage.add(evaluationUsage, usage2);
1858
- if (options.cost !== void 0 && result.targetStatus === "succeeded") {
1859
- const metric = options.metrics.find(
1860
- (candidate) => candidate.name === metricResult.metricName
1861
- );
1862
- if (metric !== void 0) {
1863
- const metricCost = await calculateCost(
1864
- options.cost.calculate({
1865
- kind: "evaluation",
1866
- suiteName: options.name,
1867
- case: result.case,
1868
- output: result.output,
1869
- metric,
1870
- usage: usage2
1871
- })
1872
- );
1873
- metricResult.cost = metricCost;
1874
- caseEvaluationCost += metricCost;
1875
- evaluationCost += metricCost;
1876
- }
1877
- }
1878
- }
1879
- result.usage = {
1880
- target: caseTargetUsage,
1881
- evaluation: caseEvaluationUsage,
1882
- total: Usage.add(caseTargetUsage, caseEvaluationUsage)
1883
- };
1884
- if (options.cost !== void 0) {
1885
- result.cost = {
1886
- currency: options.cost.currency,
1887
- target: caseTargetCost,
1888
- evaluation: caseEvaluationCost,
1889
- total: caseTargetCost + caseEvaluationCost
1890
- };
1891
- }
1892
- }
1893
- const usage = {
1894
- target: targetUsage,
1895
- evaluation: evaluationUsage,
1896
- total: Usage.add(targetUsage, evaluationUsage)
1897
- };
1898
- const aggregates = {
1899
- metrics: countMetricOutcomes(results),
1900
- cases: countCaseOutcomes(results),
1901
- usage
1902
- };
1903
- if (options.cost !== void 0) {
1904
- aggregates.cost = {
1905
- currency: options.cost.currency,
1906
- target: targetCost,
1907
- evaluation: evaluationCost,
1908
- total: targetCost + evaluationCost
1909
- };
1910
- }
1911
- return aggregates;
1912
- }
1913
- async function resolveTargetUsage(options, testCase, output) {
1914
- const usage = options.targetUsage === void 0 ? usageFromOutput(output) : await options.targetUsage({
1915
- suiteName: options.name,
1916
- case: testCase,
1917
- output,
1918
- signal: new AbortController().signal
1919
- });
1920
- if (usage !== void 0) assertUsage(usage, `Target usage for case ${testCase.id}`);
1921
- return usage;
1922
- }
1923
- function usageFromOutput(output) {
1924
- if (typeof output !== "object" || output === null || !("usage" in output)) return void 0;
1925
- return output.usage;
1926
- }
1927
- function assertUsage(usage, label) {
1928
- for (const [key, value] of Object.entries(usage)) {
1929
- if (key === "details") continue;
1930
- if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
1931
- throw new TypeError(`${label} must contain finite, non-negative token counts`);
1932
- }
1933
- }
1934
- }
1935
- async function calculateCost(value) {
1936
- const cost = await value;
1937
- if (!Number.isFinite(cost) || cost < 0) {
1938
- throw new TypeError("Evaluation cost calculator must return a finite, non-negative number");
1939
- }
1940
- return cost;
1941
- }
1942
- function validateSuiteOptions(options) {
1943
- if (options.name.trim().length === 0) {
1944
- throw new TypeError("Evaluation suite name must not be empty");
1945
- }
1946
- if (options.cases.length === 0) {
1947
- throw new TypeError("Evaluation suite must contain at least one case");
1948
- }
1949
- if (options.metrics.length === 0) {
1950
- throw new TypeError("Evaluation suite must contain at least one metric");
1951
- }
1952
- for (const testCase of options.cases) {
1953
- if (testCase.id.trim().length === 0) {
1954
- throw new TypeError("Evaluation case id must not be empty");
1955
- }
1956
- }
1957
- for (const metric of options.metrics) {
1958
- if (metric.name.trim().length === 0) {
1959
- throw new TypeError("Evaluation metric name must not be empty");
1960
- }
1961
- }
1962
- assertUnique(
1963
- options.cases.map((testCase) => testCase.id),
1964
- "Evaluation case id"
1965
- );
1966
- assertUnique(
1967
- options.metrics.map((metric) => metric.name),
1968
- "Evaluation metric name"
1969
- );
1970
- if (options.cost !== void 0 && options.cost.currency.trim().length === 0) {
1971
- throw new TypeError("Evaluation cost currency must not be empty");
1972
- }
1973
- for (const [label, value] of [
1974
- ["concurrency", options.concurrency],
1975
- ["targetConcurrency", options.targetConcurrency],
1976
- ["metricConcurrency", options.metricConcurrency]
1977
- ]) {
1978
- if (value !== void 0 && (!Number.isSafeInteger(value) || value < 1)) {
1979
- throw new RangeError(`Evaluation ${label} must be a positive integer`);
1980
- }
1981
- }
1982
- if (options.caseTimeoutMs !== void 0 && (!Number.isSafeInteger(options.caseTimeoutMs) || options.caseTimeoutMs < 1)) {
1983
- throw new RangeError("Evaluation caseTimeoutMs must be a positive integer");
1984
- }
1985
- if (options.shard !== void 0) {
1986
- if (!Number.isSafeInteger(options.shard.count) || options.shard.count < 1) {
1987
- throw new RangeError("Evaluation shard count must be a positive integer");
1988
- }
1989
- if (!Number.isSafeInteger(options.shard.index) || options.shard.index < 0 || options.shard.index >= options.shard.count) {
1990
- throw new RangeError("Evaluation shard index must be between 0 and count - 1");
1991
- }
1992
- }
1993
- }
1994
- function assertUnique(values, label) {
1995
- const seen = /* @__PURE__ */ new Set();
1996
- for (const value of values) {
1997
- if (seen.has(value)) throw new TypeError(`${label} must be unique: ${value}`);
1998
- seen.add(value);
1999
- }
2000
- }
2001
- function selectCases(options) {
2002
- const requested = options.caseIds === void 0 ? void 0 : new Set(options.caseIds);
2003
- if (requested !== void 0) {
2004
- assertUnique([...options.caseIds], "Evaluation selected case id");
2005
- const available = new Set(options.cases.map((testCase) => testCase.id));
2006
- for (const id of requested) {
2007
- if (!available.has(id))
2008
- throw new TypeError(`Evaluation selected case id was not found: ${id}`);
2009
- }
2010
- }
2011
- const filtered = options.cases.filter(
2012
- (testCase, index) => (requested === void 0 || requested.has(testCase.id)) && (options.caseFilter === void 0 || options.caseFilter(testCase, index))
2013
- );
2014
- if (options.shard === void 0) return filtered;
2015
- return filtered.filter((_, index) => index % options.shard.count === options.shard.index);
2016
- }
2017
- async function notifyProgress(options, event) {
2018
- await options.onProgress?.(event);
2019
- }
2020
- function isAborted(signal) {
2021
- return signal?.aborted === true;
2022
- }
2023
- function suiteAbortReason(signal) {
2024
- return signal?.reason ?? new EvalAbortError();
2025
- }
2026
-
2027
- // src/evals/cli.ts
2028
- var EvalAssertionError = class extends Error {
2029
- mismatches;
2030
- constructor(message, mismatches) {
2031
- super(`${message}
2032
- ${mismatches.map((mismatch) => `- ${mismatch}`).join("\n")}`);
2033
- this.name = "EvalAssertionError";
2034
- this.mismatches = mismatches;
2035
- }
2036
- };
2037
- function defineEvalExpectations(_suite, expectations) {
2038
- return expectations;
2039
- }
2040
- function formatEvalResult(result, options = {}) {
2041
- const format = options.format ?? "pretty";
2042
- if (format === "quiet") return "";
2043
- validatePrintOptions(options);
2044
- return format === "json" ? jsonResult(result, options) : prettyResult(result, options);
2045
- }
2046
- function printEvalResult(result, options = {}) {
2047
- const format = options.format ?? "pretty";
2048
- if (format === "quiet") return;
2049
- const write = options.output?.stdout ?? ((text) => process.stdout.write(text));
2050
- write(`${formatEvalResult(result, options)}
2051
- `);
2052
- }
2053
- function evalExitCode(result, expectations) {
2054
- const hasExpectations = expectations?.totals !== void 0 || expectations?.outcomes !== void 0;
2055
- const mismatches = hasExpectations ? expectationMismatches(result, expectations) : [];
2056
- if (hasExpectations && mismatches.length === 0) return 0;
2057
- if (hasExpectations && hasUnexpectedInvalid(result, expectations)) return 2;
2058
- if (hasExpectations) return 1;
2059
- if (requiredMetricCount(result, "invalid") > 0) return 2;
2060
- return requiredMetricCount(result, "fail") > 0 ? 1 : 0;
2061
- }
2062
- function assertEvalTotals(result, expected) {
2063
- const mismatches = totalMismatches(result, expected);
2064
- if (mismatches.length > 0) {
2065
- throw new EvalAssertionError("Evaluation totals did not match expectations.", mismatches);
2066
- }
2067
- }
2068
- function assertEvalOutcomes(result, expected) {
2069
- const mismatches = outcomeMismatches(result, expected);
2070
- if (mismatches.length > 0) {
2071
- throw new EvalAssertionError("Evaluation outcomes did not match expectations.", mismatches);
2072
- }
2073
- }
2074
- async function runEvalCli(options) {
2075
- const { format, exitCode, expectations, output, maxValueLength, redact: redact2, ...suiteOptions } = options;
2076
- const result = await runEvalSuite(
2077
- suiteOptions
2078
- );
2079
- printEvalResult(result, { format, output, maxValueLength, redact: redact2 });
2080
- const code = evalExitCode(result, expectations);
2081
- const mismatches = expectationMismatches(result, expectations);
2082
- if (mismatches.length > 0 && format !== "quiet") {
2083
- const write = output?.stderr ?? ((text) => process.stderr.write(text));
2084
- write(
2085
- `Evaluation expectation mismatches:
2086
- ${mismatches.map((value) => `- ${value}`).join("\n")}
2087
- `
2088
- );
2089
- }
2090
- const currentExitCode = typeof process.exitCode === "number" ? process.exitCode : Number(process.exitCode ?? 0);
2091
- if (exitCode === true && code > currentExitCode) process.exitCode = code;
2092
- return result;
2093
- }
2094
- function prettyResult(result, options) {
2095
- const lines = [
2096
- `${result.name} (${result.run.id})`,
2097
- `Cases: ${totalsText(result.cases)}`,
2098
- `Metrics: ${totalsText(result.metrics)}`
2099
- ];
2100
- for (const caseResult of result.results) {
2101
- lines.push(``, `[${caseResult.outcome.toUpperCase()}] ${caseResult.case.id}`);
2102
- if (caseResult.targetStatus === "succeeded") {
2103
- lines.push(
2104
- ` output: ${displayValue(
2105
- redact(caseResult.output, options, { kind: "output", caseId: caseResult.case.id }),
2106
- options.maxValueLength
2107
- )}`
2108
- );
2109
- }
2110
- if (caseResult.targetStatus === "failed") {
2111
- lines.push(
2112
- ` target error: ${errorText(
2113
- redact(caseResult.targetError, options, { kind: "error", caseId: caseResult.case.id }),
2114
- options.maxValueLength
2115
- )}`
2116
- );
2117
- }
2118
- for (const metric of caseResult.metrics) {
2119
- const parts = [` - ${metric.metricName}: ${metric.outcome.outcome}`];
2120
- if (metric.outcome.score !== void 0) {
2121
- parts.push(
2122
- `score=${displayValue(
2123
- redact(metric.outcome.score, options, {
2124
- kind: "score",
2125
- caseId: caseResult.case.id,
2126
- metricName: metric.metricName
2127
- }),
2128
- options.maxValueLength
2129
- )}`
2130
- );
2131
- }
2132
- if (metric.threshold !== void 0) parts.push(`threshold=${metric.threshold}`);
2133
- if (metric.direction !== void 0) parts.push(`direction=${metric.direction}`);
2134
- if (!metric.required) parts.push("optional");
2135
- lines.push(parts.join(" | "));
2136
- const explanation = metric.outcome.comment ?? (metric.outcome.outcome === "invalid" ? metric.outcome.reason : void 0);
2137
- if (explanation !== void 0) {
2138
- lines.push(
2139
- ` ${displayValue(
2140
- redact(explanation, options, {
2141
- kind: "comment",
2142
- caseId: caseResult.case.id,
2143
- metricName: metric.metricName
2144
- }),
2145
- options.maxValueLength
2146
- )}`
2147
- );
2148
- }
2149
- }
2150
- }
2151
- lines.push(
2152
- ``,
2153
- `Usage: target=${result.usage.target.totalTokens} evaluation=${result.usage.evaluation.totalTokens} total=${result.usage.total.totalTokens} tokens`
2154
- );
2155
- if (result.cost !== void 0) {
2156
- lines.push(
2157
- `Cost: target=${result.cost.target} evaluation=${result.cost.evaluation} total=${result.cost.total} ${result.cost.currency}`
2158
- );
2159
- }
2160
- lines.push(`Duration: ${result.durationMs}ms`);
2161
- return lines.join("\n");
2162
- }
2163
- function jsonResult(result, options) {
2164
- return JSON.stringify(
2165
- redactJsonResult(result, options),
2166
- (_key, value) => {
2167
- if (value instanceof Error) {
2168
- return { name: value.name, message: value.message, stack: value.stack };
2169
- }
2170
- if (value instanceof RegExp) return String(value);
2171
- if (typeof value === "string") return truncate(value, options.maxValueLength);
2172
- return value;
2173
- },
2174
- 2
2175
- );
2176
- }
2177
- function expectationMismatches(result, expectations) {
2178
- if (expectations === void 0) return [];
2179
- const mismatches = [];
2180
- if (expectations.totals !== void 0) {
2181
- mismatches.push(...totalMismatches(result, expectations.totals));
2182
- }
2183
- if (expectations.outcomes !== void 0) {
2184
- mismatches.push(...outcomeMismatches(result, expectations.outcomes));
2185
- }
2186
- return mismatches;
2187
- }
2188
- function totalMismatches(result, expected) {
2189
- const directMetrics = {};
2190
- if (expected.total !== void 0) directMetrics.total = expected.total;
2191
- if (expected.passed !== void 0) directMetrics.passed = expected.passed;
2192
- if (expected.failed !== void 0) directMetrics.failed = expected.failed;
2193
- if (expected.invalid !== void 0) directMetrics.invalid = expected.invalid;
2194
- return [
2195
- ...totalsGroupMismatches("metrics", result.metrics, {
2196
- ...directMetrics,
2197
- ...expected.metrics
2198
- }),
2199
- ...totalsGroupMismatches("cases", result.cases, expected.cases)
2200
- ];
2201
- }
2202
- function totalsGroupMismatches(label, actual, expected) {
2203
- if (expected === void 0) return [];
2204
- const mismatches = [];
2205
- for (const key of ["total", "passed", "failed", "invalid"]) {
2206
- if (expected[key] !== void 0 && actual[key] !== expected[key]) {
2207
- mismatches.push(`${label}.${key}: expected ${expected[key]}, received ${actual[key]}`);
2208
- }
2209
- }
2210
- return mismatches;
2211
- }
2212
- function outcomeMismatches(result, expected) {
2213
- const mismatches = [];
2214
- const actualCases = new Map(result.results.map((caseResult) => [caseResult.case.id, caseResult]));
2215
- for (const [caseId, metrics] of Object.entries(expected)) {
2216
- const caseResult = actualCases.get(caseId);
2217
- if (caseResult === void 0) {
2218
- mismatches.push(`${caseId}: expected case was not present`);
2219
- continue;
2220
- }
2221
- for (const [metricName, expectedOutcome] of Object.entries(metrics)) {
2222
- const metric = caseResult.metrics.find((candidate) => candidate.metricName === metricName);
2223
- if (metric === void 0) {
2224
- mismatches.push(`${caseId}.${metricName}: expected metric was not present`);
2225
- } else if (metric.outcome.outcome !== expectedOutcome) {
2226
- mismatches.push(
2227
- `${caseId}.${metricName}: expected ${expectedOutcome}, received ${metric.outcome.outcome}`
2228
- );
2229
- }
2230
- }
2231
- }
2232
- for (const caseResult of result.results) {
2233
- for (const metric of caseResult.metrics) {
2234
- if (!metric.required) continue;
2235
- const expectedOutcome = expected[caseResult.case.id]?.[metric.metricName] ?? "pass";
2236
- if (metric.outcome.outcome !== expectedOutcome) {
2237
- const message = `${caseResult.case.id}.${metric.metricName}: expected ${expectedOutcome}, received ${metric.outcome.outcome}`;
2238
- if (!mismatches.includes(message)) mismatches.push(message);
2239
- }
2240
- }
2241
- }
2242
- return mismatches;
2243
- }
2244
- function hasUnexpectedInvalid(result, expectations) {
2245
- if (expectations?.outcomes !== void 0) {
2246
- return result.results.some(
2247
- (caseResult) => caseResult.metrics.some(
2248
- (metric) => metric.required && metric.outcome.outcome === "invalid" && expectations.outcomes?.[caseResult.case.id]?.[metric.metricName] !== "invalid"
2249
- )
2250
- );
2251
- }
2252
- const expectedInvalid = expectations?.totals?.metrics?.invalid ?? expectations?.totals?.invalid;
2253
- return result.metrics.invalid > (expectedInvalid ?? 0);
2254
- }
2255
- function requiredMetricCount(result, status) {
2256
- return result.results.reduce(
2257
- (total, caseResult) => total + caseResult.metrics.filter((metric) => metric.required && metric.outcome.outcome === status).length,
2258
- 0
2259
- );
2260
- }
2261
- function totalsText(totals) {
2262
- return `${totals.total} total / ${totals.passed} pass / ${totals.failed} fail / ${totals.invalid} invalid`;
2263
- }
2264
- function displayValue(value, maxValueLength) {
2265
- let text;
2266
- if (typeof value === "string") text = value;
2267
- else {
2268
- try {
2269
- text = JSON.stringify(value) ?? String(value);
2270
- } catch {
2271
- text = String(value);
2272
- }
2273
- }
2274
- return truncate(text, maxValueLength);
2275
- }
2276
- function errorText(error, maxValueLength) {
2277
- return truncate(error instanceof Error ? error.message : displayValue(error), maxValueLength);
2278
- }
2279
- function truncate(value, maxValueLength) {
2280
- return maxValueLength !== void 0 && value.length > maxValueLength ? `${value.slice(0, maxValueLength)}\u2026` : value;
2281
- }
2282
- function redact(value, options, context) {
2283
- return options.redact === void 0 ? value : options.redact(value, context);
2284
- }
2285
- function redactJsonResult(result, options) {
2286
- return {
2287
- ...result,
2288
- run: {
2289
- ...result.run,
2290
- metadata: result.run.metadata === void 0 ? void 0 : redact(result.run.metadata, options, {
2291
- kind: "metadata"
2292
- })
2293
- },
2294
- results: result.results.map((caseResult) => ({
2295
- ...caseResult,
2296
- case: {
2297
- ...caseResult.case,
2298
- input: redact(caseResult.case.input, options, {
2299
- kind: "input",
2300
- caseId: caseResult.case.id
2301
- }),
2302
- expected: redact(caseResult.case.expected, options, {
2303
- kind: "expected",
2304
- caseId: caseResult.case.id
2305
- }),
2306
- context: redact(caseResult.case.context, options, {
2307
- kind: "context",
2308
- caseId: caseResult.case.id
2309
- }),
2310
- retrievalContext: redact(caseResult.case.retrievalContext, options, {
2311
- kind: "retrievalContext",
2312
- caseId: caseResult.case.id
2313
- }),
2314
- metadata: caseResult.case.metadata === void 0 ? void 0 : redact(caseResult.case.metadata, options, {
2315
- kind: "metadata",
2316
- caseId: caseResult.case.id
2317
- })
2318
- },
2319
- output: caseResult.targetStatus === "succeeded" ? redact(caseResult.output, options, { kind: "output", caseId: caseResult.case.id }) : void 0,
2320
- targetError: caseResult.targetStatus === "failed" ? redact(caseResult.targetError, options, {
2321
- kind: "error",
2322
- caseId: caseResult.case.id
2323
- }) : void 0,
2324
- metrics: caseResult.metrics.map((metric) => ({
2325
- ...metric,
2326
- reporterErrors: metric.reporterErrors.map(
2327
- (error) => redact(error, options, {
2328
- kind: "error",
2329
- caseId: caseResult.case.id,
2330
- metricName: metric.metricName
2331
- })
2332
- ),
2333
- outcome: redactOutcome(metric.outcome, options, caseResult.case.id, metric.metricName)
2334
- })),
2335
- scores: Object.fromEntries(
2336
- caseResult.metrics.map((metric) => [
2337
- metric.metricName,
2338
- redactOutcome(metric.outcome, options, caseResult.case.id, metric.metricName)
2339
- ])
2340
- )
2341
- })),
2342
- reporterErrors: result.reporterErrors.map((error) => redact(error, options, { kind: "error" }))
2343
- };
2344
- }
2345
- function redactOutcome(outcome, options, caseId, metricName) {
2346
- return {
2347
- ...outcome,
2348
- ...outcome.score === void 0 ? {} : { score: redact(outcome.score, options, { kind: "score", caseId, metricName }) },
2349
- ...outcome.comment === void 0 ? {} : { comment: redact(outcome.comment, options, { kind: "comment", caseId, metricName }) },
2350
- ...!("reason" in outcome) || outcome.reason === void 0 ? {} : { reason: redact(outcome.reason, options, { kind: "comment", caseId, metricName }) },
2351
- ...outcome.metadata === void 0 ? {} : {
2352
- metadata: redact(outcome.metadata, options, {
2353
- kind: "metadata",
2354
- caseId,
2355
- metricName
2356
- })
2357
- },
2358
- ...!("error" in outcome) || outcome.error === void 0 ? {} : { error: redact(outcome.error, options, { kind: "error", caseId, metricName }) }
2359
- };
2360
- }
2361
- function validatePrintOptions(options) {
2362
- if (options.maxValueLength !== void 0 && (!Number.isSafeInteger(options.maxValueLength) || options.maxValueLength < 1)) {
2363
- throw new RangeError("Evaluation maxValueLength must be a positive integer.");
2364
- }
2365
- }
2366
-
2367
- // src/evals/metric.ts
2368
- function defineMetric(metric) {
2369
- return metric;
2370
- }
2371
-
2372
- // src/evals/metrics.ts
2373
- import { z as z2 } from "zod";
2374
- function exactMatch(options = {}) {
2375
- return {
2376
- name: options.name ?? "exact_match",
2377
- required: options.required ?? true,
2378
- dataType: "BOOLEAN",
2379
- direction: "higher_is_better",
2380
- threshold: 1,
2381
- async evaluate(args) {
2382
- const actual = await resolveActual(options.actual, args);
2383
- const expected = await resolveExpected(options.expected, args);
2384
- if (expected === void 0) {
2385
- return EvalOutcome.invalid("No expected value provided for exact match.");
2386
- }
2387
- const passed = evalValuesEqual(actual, expected);
2388
- return passed ? EvalOutcome.pass(true) : EvalOutcome.fail(false, { comment: `Expected ${formatValue(expected)}.` });
2389
- }
2390
- };
2391
- }
2392
- function contains(options = {}) {
2393
- return {
2394
- name: options.name ?? "contains",
2395
- required: options.required ?? true,
2396
- dataType: "BOOLEAN",
2397
- direction: "higher_is_better",
2398
- threshold: 1,
2399
- async evaluate(args) {
2400
- const actual = await resolveActualText(options.actual, args);
2401
- const expected = await resolveExpected(options.expected, args);
2402
- if (expected === void 0) {
2403
- return EvalOutcome.invalid("No expected value provided for contains.");
2404
- }
2405
- if (typeof expected !== "string" && !(expected instanceof RegExp)) {
2406
- return EvalOutcome.invalid("Contains expected value must be a string or RegExp.");
2407
- }
2408
- const passed = expected instanceof RegExp ? regexMatches(expected, actual) : actual.includes(expected);
2409
- return passed ? EvalOutcome.pass(true) : EvalOutcome.fail(false, { comment: `Output did not contain ${String(expected)}.` });
2410
- }
2411
- };
2412
- }
2413
- function notContains(options = {}) {
2414
- return {
2415
- name: options.name ?? "not_contains",
2416
- required: options.required ?? true,
2417
- dataType: "BOOLEAN",
2418
- direction: "higher_is_better",
2419
- threshold: 1,
2420
- async evaluate(args) {
2421
- const actual = await resolveActualText(options.actual, args);
2422
- const expected = await resolveExpected(options.expected, args);
2423
- if (expected === void 0) {
2424
- return EvalOutcome.invalid("No expected value provided for notContains.");
2425
- }
2426
- if (typeof expected !== "string" && !(expected instanceof RegExp)) {
2427
- return EvalOutcome.invalid("notContains expected value must be a string or RegExp.");
2428
- }
2429
- const found = textExpectationMatches(expected, actual);
2430
- return found ? EvalOutcome.fail(false, {
2431
- comment: `Output contained forbidden value ${String(expected)}.`
2432
- }) : EvalOutcome.pass(true);
2433
- }
2434
- };
2435
- }
2436
- function containsAll(options) {
2437
- return containsListMetric("contains_all", "all", options);
2438
- }
2439
- function containsAny(options) {
2440
- return containsListMetric("contains_any", "any", options);
2441
- }
2442
- function containsListMetric(defaultName, mode, options) {
2443
- return {
2444
- name: options.name ?? defaultName,
2445
- required: options.required ?? true,
2446
- dataType: "BOOLEAN",
2447
- direction: "higher_is_better",
2448
- threshold: 1,
2449
- async evaluate(args) {
2450
- const actual = await resolveActualText(options.actual, args);
2451
- const expected = await resolveExpected(options.expected, args);
2452
- if (!Array.isArray(expected) || expected.length === 0) {
2453
- return EvalOutcome.invalid(`${defaultName} expected value must be a non-empty array.`);
2454
- }
2455
- if (expected.some((value) => typeof value !== "string" && !(value instanceof RegExp))) {
2456
- return EvalOutcome.invalid(`${defaultName} expected values must be strings or RegExp.`);
2457
- }
2458
- const matches2 = expected.map((value) => textExpectationMatches(value, actual));
2459
- const passed = mode === "all" ? matches2.every(Boolean) : matches2.some(Boolean);
2460
- if (passed) return EvalOutcome.pass(true);
2461
- const missing = expected.filter((_, index) => !matches2[index]).map(String);
2462
- const comment = mode === "all" ? `Output was missing: ${missing.join(", ")}.` : `Output matched none of: ${expected.map(String).join(", ")}.`;
2463
- return EvalOutcome.fail(false, { comment });
2464
- }
2465
- };
2466
- }
2467
- function matches(options) {
2468
- return regexMetric("matches", false, options);
2469
- }
2470
- function doesNotMatch(options) {
2471
- return regexMetric("does_not_match", true, options);
2472
- }
2473
- function regexMetric(defaultName, negate, options) {
2474
- return {
2475
- name: options.name ?? defaultName,
2476
- required: options.required ?? true,
2477
- dataType: "BOOLEAN",
2478
- direction: "higher_is_better",
2479
- threshold: 1,
2480
- async evaluate(args) {
2481
- const actual = await resolveActualText(options.actual, args);
2482
- const expected = await resolveExpected(options.expected, args);
2483
- if (!(expected instanceof RegExp)) {
2484
- return EvalOutcome.invalid(`${defaultName} expected value must be a RegExp.`);
2485
- }
2486
- const matched = regexMatches(expected, actual);
2487
- const passed = negate ? !matched : matched;
2488
- return passed ? EvalOutcome.pass(true) : EvalOutcome.fail(false, {
2489
- comment: negate ? `Output matched forbidden pattern ${String(expected)}.` : `Output did not match ${String(expected)}.`
2490
- });
2491
- }
2492
- };
2493
- }
2494
- function maxLength(options) {
2495
- return {
2496
- name: options.name ?? "max_length",
2497
- required: options.required ?? true,
2498
- dataType: "BOOLEAN",
2499
- direction: "higher_is_better",
2500
- threshold: 1,
2501
- async evaluate(args) {
2502
- const actual = await resolveActualText(options.actual, args);
2503
- const max = await resolveOption(options.max, args);
2504
- if (!Number.isInteger(max) || max < 0) {
2505
- return EvalOutcome.invalid("maxLength max must be a non-negative integer.");
2506
- }
2507
- const length = Array.from(actual).length;
2508
- return length <= max ? EvalOutcome.pass(true) : EvalOutcome.fail(false, { comment: `Output length ${length} exceeded maximum ${max}.` });
2509
- }
2510
- };
2511
- }
2512
- function requiredFields(options) {
2513
- return {
2514
- name: options.name ?? "required_fields",
2515
- required: options.required ?? true,
2516
- dataType: "BOOLEAN",
2517
- direction: "higher_is_better",
2518
- threshold: 1,
2519
- async evaluate(args) {
2520
- const actual = await resolveActual(options.actual, args);
2521
- const expected = await resolveOption(options.expected, args);
2522
- if (!Array.isArray(expected) || expected.length === 0 || expected.some((field) => typeof field !== "string" || field.length === 0)) {
2523
- return EvalOutcome.invalid(
2524
- "requiredFields expected value must be a non-empty string array."
2525
- );
2526
- }
2527
- if (typeof actual !== "object" || actual === null || Array.isArray(actual)) {
2528
- return EvalOutcome.invalid("requiredFields actual value must be an object.");
2529
- }
2530
- const missing = expected.filter((field) => !Object.hasOwn(actual, field));
2531
- return missing.length === 0 ? EvalOutcome.pass(true) : EvalOutcome.fail(false, { comment: `Missing required fields: ${missing.join(", ")}.` });
2532
- }
2533
- };
2534
- }
2535
- function regexMatches(pattern, text) {
2536
- pattern.lastIndex = 0;
2537
- const matched = pattern.test(text);
2538
- pattern.lastIndex = 0;
2539
- return matched;
2540
- }
2541
- function textExpectationMatches(expected, actual) {
2542
- return expected instanceof RegExp ? regexMatches(expected, actual) : actual.includes(expected);
2543
- }
2544
- async function resolveOption(value, args) {
2545
- return typeof value === "function" ? value(args) : value;
2546
- }
2547
- function semanticSimilarity(options) {
2548
- const threshold = unitInterval(options.threshold, "semanticSimilarity threshold");
2549
- return {
2550
- name: options.name ?? "semantic_similarity",
2551
- required: options.required ?? true,
2552
- dataType: "NUMERIC",
2553
- direction: "higher_is_better",
2554
- threshold,
2555
- async evaluate(args) {
2556
- const actual = await resolveActualText(options.actual, args);
2557
- const expected = await resolveExpected(options.expected, args);
2558
- if (expected === void 0) {
2559
- return EvalOutcome.invalid("No expected value provided for semantic similarity.");
2560
- }
2561
- if (typeof expected !== "string") {
2562
- return EvalOutcome.invalid("Semantic similarity expected value must be a string.");
2563
- }
2564
- const [{ embedding: actualEmbedding }, { embedding: expectedEmbedding }] = await Promise.all([
2565
- embedText({ model: options.model, text: actual }),
2566
- embedText({ model: options.model, text: expected })
2567
- ]);
2568
- const score = cosineSimilarity(actualEmbedding.vector, expectedEmbedding.vector);
2569
- return score >= threshold ? EvalOutcome.pass(score) : EvalOutcome.fail(score, { comment: `Similarity below threshold ${threshold}.` });
2570
- }
2571
- };
2572
- }
2573
- function llmJudge(options) {
2574
- const retries = extractionRetries(options.retries);
2575
- return {
2576
- name: options.name ?? "llm_judge",
2577
- required: options.required ?? true,
2578
- async evaluate(args) {
2579
- try {
2580
- const result = await extract({
2581
- model: options.model,
2582
- outputSchema: options.schema,
2583
- instructions: options.instructions ?? "Judge the eval case by the requested schema. Submit the judgment using the schema.",
2584
- text: await resolveJudgePrompt(options.prompt, args),
2585
- retries
2586
- });
2587
- return options.passes(result.output) ? EvalOutcome.pass(result.output, { usage: result.usage }) : EvalOutcome.fail(result.output, { usage: result.usage });
2588
- } catch (error) {
2589
- return EvalOutcome.fromError(error);
2590
- }
2591
- }
2592
- };
2593
- }
2594
- function llmScore(options) {
2595
- const criteria = Array.isArray(options.criteria) ? options.criteria.join("\n") : options.criteria;
2596
- if (criteria.trim().length === 0) throw new TypeError("llmScore criteria must not be empty.");
2597
- const threshold = unitInterval(options.threshold, "llmScore threshold");
2598
- const retries = extractionRetries(options.retries);
2599
- return {
2600
- name: options.name ?? "llm_score",
2601
- required: options.required ?? true,
2602
- dataType: "NUMERIC",
2603
- projectScore: (score) => score.score,
2604
- direction: "higher_is_better",
2605
- threshold,
2606
- async evaluate(args) {
2607
- try {
2608
- const result = await extract({
2609
- model: options.model,
2610
- outputSchema: z2.object({
2611
- score: z2.number(),
2612
- feedback: z2.string()
2613
- }),
2614
- instructions: options.instructions ?? `Score the eval case against these criteria:
2615
- ${criteria}
2616
-
2617
- Return a score between 0 and 1 and brief feedback.`,
2618
- text: await resolveJudgePrompt(options.prompt, args),
2619
- retries
2620
- });
2621
- const score = result.output;
2622
- if (score.score < 0 || score.score > 1) {
2623
- return EvalOutcome.invalid(`Score ${score.score} outside valid range [0, 1].`, {
2624
- score,
2625
- usage: result.usage
2626
- });
2627
- }
2628
- return score.score >= threshold ? EvalOutcome.pass(score, { comment: score.feedback, usage: result.usage }) : EvalOutcome.fail(score, { comment: score.feedback, usage: result.usage });
2629
- } catch (error) {
2630
- return EvalOutcome.fromError(error);
2631
- }
2632
- }
2633
- };
2634
- }
2635
- function extractionRetries(retries) {
2636
- const retryCount = retries ?? 0;
2637
- if (!Number.isInteger(retryCount) || retryCount < 0) {
2638
- throw new RangeError("Eval metric retries must be a non-negative integer.");
2639
- }
2640
- if (retryCount === 0) {
2641
- return void 0;
2642
- }
2643
- return { maxAttempts: retryCount + 1 };
2644
- }
2645
- function unitInterval(value, label) {
2646
- if (!Number.isFinite(value) || value < 0 || value > 1) {
2647
- throw new RangeError(`${label} must be between 0 and 1.`);
2648
- }
2649
- return value;
2650
- }
2651
-
2652
- // src/evals/suite.ts
2653
- function defineEvalCases(cases) {
2654
- return cases;
2655
- }
2656
- function createEvalTypes() {
2657
- return {
2658
- defineMetric(metric) {
2659
- return metric;
2660
- }
2661
- };
2662
- }
2663
- function defineEvalSuite(options) {
2664
- if (options !== void 0) return options;
2665
- return createEvalTypes();
2666
- }
31
+ defineMetric
32
+ } from "../chunk-F2OKLHGB.js";
33
+ import {
34
+ contains,
35
+ containsAll,
36
+ containsAny,
37
+ doesNotMatch,
38
+ exactMatch,
39
+ llmJudge,
40
+ llmScore,
41
+ matches,
42
+ maxLength,
43
+ notContains,
44
+ requiredFields,
45
+ semanticSimilarity
46
+ } from "../chunk-PYLPLFJZ.js";
47
+ import {
48
+ abstention,
49
+ answerRelevancy,
50
+ faithfulness,
51
+ gEval,
52
+ hallucination,
53
+ jsonCorrectness,
54
+ knowledgeRetention,
55
+ promptAlignment,
56
+ summarization,
57
+ turnRelevancy
58
+ } from "../chunk-BUPC72Y2.js";
59
+ import "../chunk-LKIABZNR.js";
60
+ import {
61
+ selectEvalCaseIds,
62
+ selectPromptOutput
63
+ } from "../chunk-ZPXOBQDS.js";
64
+ import "../chunk-ZYXMWEL4.js";
65
+ import {
66
+ EvalOutcome
67
+ } from "../chunk-EJR6VVB3.js";
68
+ import "../chunk-3P3YVJ7V.js";
69
+ import "../chunk-UOGM62JL.js";
70
+ import {
71
+ AgentEvalSuspensionError,
72
+ agentEvalTarget
73
+ } from "../chunk-NNEKBZSM.js";
74
+ import "../chunk-TP3MCUXS.js";
75
+ import "../chunk-6RQYWZI3.js";
76
+ import "../chunk-NF6WBPFG.js";
77
+ import "../chunk-ERN7P6Q4.js";
78
+ import "../chunk-7F53DOML.js";
79
+ import "../chunk-HHMLE3TZ.js";
80
+ import "../chunk-DU4WA6LQ.js";
81
+ import "../chunk-4FIVU53H.js";
82
+ import "../chunk-BDKFFFVX.js";
83
+ import "../chunk-CKKNO4XB.js";
84
+ import "../chunk-4ONUNWGC.js";
85
+ import "../chunk-UTAB3XQI.js";
86
+ import "../chunk-XQV3XNVT.js";
87
+ import "../chunk-IDNL6IH4.js";
88
+ import "../chunk-BONQTXRQ.js";
89
+ import "../chunk-4C7AXYOM.js";
90
+ import "../chunk-SQAAVYJG.js";
91
+ import "../chunk-POXHJF3H.js";
92
+ import "../chunk-USRKPEQN.js";
93
+ import "../chunk-WN6AVBO4.js";
2667
94
  export {
2668
95
  AgentEvalSuspensionError,
2669
96
  EvalAbortError,