promptfoo 0.121.4 → 0.121.7

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 (497) hide show
  1. package/dist/src/{ListApp-DQkFNqE9.js → ListApp-DLmM02JS.js} +1 -1
  2. package/dist/src/{accounts-DhMYUUbu.js → accounts-Ca7WIoPY.js} +12 -7
  3. package/dist/src/{accounts-F9d_5sMC.js → accounts-CjFnOPmb.js} +14 -9
  4. package/dist/src/{accounts-Dy17bs4D.cjs → accounts-CmWzeD2d.cjs} +16 -10
  5. package/dist/src/{accounts-DdJ2pHMI.js → accounts-DanM1wq_.js} +13 -8
  6. package/dist/src/{agentic-utils-qFlm6zes.js → agentic-utils-CJ0j3fBi.js} +3 -3
  7. package/dist/src/{agentic-utils-w68v6_Dz.js → agentic-utils-DDEGRV9v.js} +3 -3
  8. package/dist/src/{agentic-utils-BpX5b23w.cjs → agentic-utils-DvPWSUpb.cjs} +8 -7
  9. package/dist/src/{agentic-utils-P172hM8B.js → agentic-utils-TxUEMPYS.js} +2 -2
  10. package/dist/src/{agents-BahDpe5G.cjs → agents-B4sRuXg3.cjs} +7 -6
  11. package/dist/src/{agents-pQeBEXMm.js → agents-B8q7h_ek.js} +5 -5
  12. package/dist/src/{agents-CgaMXvLM.js → agents-CBgJvRkB.js} +21 -10
  13. package/dist/src/{agents-C-R_jfzI.js → agents-CYn2n3QP.js} +4 -4
  14. package/dist/src/{agents-8FDnTriG.js → agents-D-vDNFx4.js} +21 -10
  15. package/dist/src/{agents-aYPQLf8W.js → agents-LrHuQqr1.js} +20 -9
  16. package/dist/src/{agents-DJ35I3Nt.js → agents-QGg76OF-.js} +5 -5
  17. package/dist/src/{agents-D7-HGxUj.cjs → agents-eHZ9nlgA.cjs} +21 -10
  18. package/dist/src/{aimlapi-sgYnkE54.js → aimlapi-CJEbQ0o6.js} +7 -7
  19. package/dist/src/{aimlapi-BD6J9oKt.js → aimlapi-D5HXzZ0s.js} +6 -6
  20. package/dist/src/{aimlapi-qcK4OT55.cjs → aimlapi-T6HGNxNe.cjs} +7 -7
  21. package/dist/src/{aimlapi-BCq3MHeL.js → aimlapi-eYv3a_DK.js} +7 -7
  22. package/dist/src/app/app/tsconfig.app.tsbuildinfo +1 -1
  23. package/dist/src/app/assets/Report-BNHJKN35.js +1 -0
  24. package/dist/src/app/assets/index-BnT6P6sF.js +388 -0
  25. package/dist/src/app/assets/index-yhM8y1PP.css +1 -0
  26. package/dist/src/app/assets/{scroll-timeline-D9IT_e8Z.js → scroll-timeline-RpeTwOvs.js} +1 -1
  27. package/dist/src/app/assets/sync-5gq6fmG4.js +4 -0
  28. package/dist/src/app/assets/vendor-charts-BL9OMNU7.js +36 -0
  29. package/dist/src/app/assets/{vendor-markdown-Ch00wnNI.js → vendor-markdown-BYsQqn7Z.js} +10 -10
  30. package/dist/src/app/assets/{vendor-react-CVvmk1UB.js → vendor-react-CqWgVW6T.js} +2 -2
  31. package/dist/src/app/assets/{vendor-utils-BnEYbx2Q.js → vendor-utils-BHPO71pu.js} +1 -1
  32. package/dist/src/app/index.html +31 -6
  33. package/dist/src/{audio-COrn8rM6.js → audio-BqnRvcWG.js} +3 -3
  34. package/dist/src/{audio-DcVKoInv.js → audio-CPMtV1yR.js} +4 -4
  35. package/dist/src/{audio-B7izf48x.js → audio-DyiebVB3.js} +4 -4
  36. package/dist/src/{audio-BQtNuYBj.cjs → audio-FnxbEnSE.cjs} +4 -4
  37. package/dist/src/authoritativeMarkupInjection-BZIywVjG.js +74 -0
  38. package/dist/src/authoritativeMarkupInjection-DyAXAsSr.js +75 -0
  39. package/dist/src/authoritativeMarkupInjection-F2gBw0lN.cjs +74 -0
  40. package/dist/src/authoritativeMarkupInjection-QEQmFS83.js +74 -0
  41. package/dist/src/{base-PYJvBE1i.js → base-CKLo890h.js} +4 -3
  42. package/dist/src/{base-fZ9wgg50.js → base-Co80MMCi.js} +5 -4
  43. package/dist/src/{base-D-670DX8.cjs → base-DGJW48uz.cjs} +5 -4
  44. package/dist/src/{base-yrI1Yal4.js → base-E9I8zXjz.js} +5 -4
  45. package/dist/src/bestOfN-B3wNzjSB.js +137 -0
  46. package/dist/src/bestOfN-BBsO41z4.js +136 -0
  47. package/dist/src/bestOfN-CAwmg5UL.cjs +140 -0
  48. package/dist/src/bestOfN-_kTi8Bxe.js +136 -0
  49. package/dist/src/{blobs-D2FAd1Q5.cjs → blobs-B0977K1O.cjs} +7 -6
  50. package/dist/src/{blobs-BCZavS8s.js → blobs-CeFdPn_T.js} +3 -3
  51. package/dist/src/{blobs-BQWqnnvL.js → blobs-DODuTK-a.js} +3 -3
  52. package/dist/src/{blobs-C-F78Kfn.js → blobs-Dwef1Ao1.js} +2 -2
  53. package/dist/src/{cache-BIyPcp5v.cjs → cache-CPGUA4Yl.cjs} +135 -25
  54. package/dist/src/cache-Cf7b4pWE.js +3 -0
  55. package/dist/src/{cache-D5NZmMiT.js → cache-DIXbtkNO.js} +125 -10
  56. package/dist/src/{cache-mb7c8hbp.js → cache-DpPWrkTE.js} +128 -12
  57. package/dist/src/{cache-C4Xb-hNb.js → cache-roFAE0cI.js} +126 -11
  58. package/dist/src/{chat-I9izLm49.js → chat-CUCorGiL.js} +12 -12
  59. package/dist/src/{chat-BPXSW8Bv.cjs → chat-DG1wG4w0.cjs} +6 -6
  60. package/dist/src/{chat-BfPaS15_.js → chat-Dabu84Br.js} +12 -12
  61. package/dist/src/{chat-Dr3DUQ0D.js → chat-DqUFcWI0.js} +12 -12
  62. package/dist/src/{chat-CclRbxGf.cjs → chat-DxTDQ83C.cjs} +14 -13
  63. package/dist/src/{chat-MKxMnZJZ.js → chat-GmlolEwo.js} +4 -4
  64. package/dist/src/{chat-0bwXjVP0.js → chat-TP8Qifkh.js} +6 -6
  65. package/dist/src/{chat-mW0ORo8G.js → chat-iwaM5UTQ.js} +6 -6
  66. package/dist/src/{chatkit-zUIVoDos.js → chatkit-B6DWi70Q.js} +4 -4
  67. package/dist/src/{chatkit-BoWoSgXl.cjs → chatkit-BYveR48_.cjs} +6 -5
  68. package/dist/src/{chatkit-Cv6AhukM.js → chatkit-fARZwEfV.js} +3 -3
  69. package/dist/src/{chatkit-CJnHRRMM.js → chatkit-lb6FK02w.js} +4 -4
  70. package/dist/src/{claude-agent-sdk-Dtq_L-Sc.js → claude-agent-sdk-BQNp_y-F.js} +212 -67
  71. package/dist/src/{claude-agent-sdk-BQNuLaAK.js → claude-agent-sdk-D5Jl0SDh.js} +212 -67
  72. package/dist/src/{claude-agent-sdk-CPJo3dBQ.cjs → claude-agent-sdk-DH416NBD.cjs} +218 -72
  73. package/dist/src/{claude-agent-sdk-nfAIcxNf.js → claude-agent-sdk-x1XJ1-pU.js} +212 -67
  74. package/dist/src/{cloud-DQZ5sVjW.js → cloud-D3DiFqH6.js} +3 -3
  75. package/dist/src/cloud-p96PA4MH.js +3 -0
  76. package/dist/src/{cloudflare-ai-BIB567w6.js → cloudflare-ai-B6NVI3ax.js} +4 -4
  77. package/dist/src/{cloudflare-ai-Dl3N9OVD.cjs → cloudflare-ai-CEAW-xQa.cjs} +6 -6
  78. package/dist/src/{cloudflare-ai-DlKr0rY7.js → cloudflare-ai-RFSojyXG.js} +6 -6
  79. package/dist/src/{cloudflare-ai-DGLte7Py.js → cloudflare-ai-r4tbYmWU.js} +6 -6
  80. package/dist/src/{cloudflare-gateway-CiIZHU0Q.js → cloudflare-gateway-BCkLouto.js} +5 -5
  81. package/dist/src/{cloudflare-gateway-DI1HNP5F.js → cloudflare-gateway-BaZ4insB.js} +3 -3
  82. package/dist/src/{cloudflare-gateway-BDZrYydE.js → cloudflare-gateway-CF-Vb-2Z.js} +5 -5
  83. package/dist/src/{cloudflare-gateway-BYDp495F.cjs → cloudflare-gateway-TJMLBj6I.cjs} +5 -5
  84. package/dist/src/codex-app-server-B8KHEiF4.js +1915 -0
  85. package/dist/src/codex-app-server-CnrLBCeA.cjs +1921 -0
  86. package/dist/src/codex-app-server-DIXZ230V.js +1915 -0
  87. package/dist/src/codex-app-server-Dd22dC_N.js +1916 -0
  88. package/dist/src/{codex-sdk-CpqiOqDO.js → codex-sdk-B6Wah8Pa.js} +6 -6
  89. package/dist/src/codex-sdk-BGjVAk23.js +3 -0
  90. package/dist/src/{codex-sdk-C2_M2pl_.cjs → codex-sdk-CFF6gUyi.cjs} +18 -10
  91. package/dist/src/{codex-sdk-Rtky3M4I.js → codex-sdk-CmQABzV3.js} +6 -6
  92. package/dist/src/{codex-sdk-CErXn7qh.js → codex-sdk-D2d54RL8.js} +5 -5
  93. package/dist/src/{cometapi-CtJ-mS8R.js → cometapi-Bu9B8NUY.js} +8 -8
  94. package/dist/src/{cometapi-DT-jlVCB.js → cometapi-CtzNCHKu.js} +7 -7
  95. package/dist/src/{cometapi-UVOryo4W.cjs → cometapi-DHCDlQUI.cjs} +8 -8
  96. package/dist/src/{cometapi-BUlt_ELa.js → cometapi-OBILPLlu.js} +8 -8
  97. package/dist/src/{completion-HUe8wDhZ.js → completion-CO2e1_62.js} +6 -6
  98. package/dist/src/{completion-BozdoXba.cjs → completion-CSYfl2cd.cjs} +6 -6
  99. package/dist/src/{completion-x0a_c2y1.js → completion-DZNxcyfG.js} +6 -6
  100. package/dist/src/{completion-Dnxn7E-j.js → completion-sNvCLTAP.js} +5 -5
  101. package/dist/src/constants-BjJV0cRr.js +6 -0
  102. package/dist/src/constants-DH5XYLKZ.js +7 -0
  103. package/dist/src/constants-DZGEFLsu.js +6 -0
  104. package/dist/src/constants-a2kYssQk.cjs +11 -0
  105. package/dist/src/{createHash-4gFQpDDv.js → createHash-BtbSX3mj.js} +1 -1
  106. package/dist/src/{createHash-CwDVU5xr.js → createHash-CGVzWdjj.js} +1 -1
  107. package/dist/src/{createHash-B7KvgoOD.cjs → createHash-CSiqnK5P.cjs} +2 -2
  108. package/dist/src/{createHash-ChI45QR1.js → createHash-CgRvs4Fn.js} +1 -1
  109. package/dist/src/crescendo-BXEJK_bi.cjs +704 -0
  110. package/dist/src/crescendo-CU_Y2i-m.js +702 -0
  111. package/dist/src/crescendo-J1Xx4_zb.js +703 -0
  112. package/dist/src/crescendo-QiaSLW0d.js +701 -0
  113. package/dist/src/custom-BJfP00Bh.js +619 -0
  114. package/dist/src/custom-CZVn-1-r.js +620 -0
  115. package/dist/src/custom-Cqia7M0D.cjs +621 -0
  116. package/dist/src/custom-notggYVl.js +618 -0
  117. package/dist/src/{docker-DCgsveLD.js → docker-4D1eL6Gq.js} +6 -6
  118. package/dist/src/{docker-ClnmCf1Z.js → docker-BBv1WUDu.js} +5 -5
  119. package/dist/src/{docker-DS4_Osau.cjs → docker-D06JUoe2.cjs} +6 -6
  120. package/dist/src/{docker-CQmlA2NU.js → docker-DdJQBxK9.js} +6 -6
  121. package/dist/src/{embedding-D3xTseo7.js → embedding--UZVe4_7.js} +6 -6
  122. package/dist/src/{embedding-I45KG3o7.cjs → embedding-BbrwopfX.cjs} +6 -6
  123. package/dist/src/{embedding-nFbumxcv.js → embedding-Bi3rxrZF.js} +5 -5
  124. package/dist/src/{embedding-DD9wa3ae.js → embedding-C251p1-8.js} +6 -6
  125. package/dist/src/{errors-Cw810C93.js → errors-9PcUL8BC.js} +1 -1
  126. package/dist/src/{esm-Dh4dOLlt.js → esm-B6whoAcf.js} +2 -2
  127. package/dist/src/{esm-CtEPLdAj.cjs → esm-BIKakvNa.cjs} +8 -7
  128. package/dist/src/{esm-C7PnfdF8.js → esm-BTK1W7lG.js} +1 -1
  129. package/dist/src/{esm-tVgYPY-f.js → esm-Bexx2PFc.js} +2 -2
  130. package/dist/src/{eval-u4UVafl6.js → eval-0VRANImH.js} +21 -21
  131. package/dist/src/{eval-CzJFfFO9.js → eval-DscR5iOM.js} +1 -1
  132. package/dist/src/{evalResult-Bgm9ZH31.js → evalResult-2RRJvFyB.js} +41 -16
  133. package/dist/src/{evalResult-KZqXl4XP.cjs → evalResult-CvtS8h8u.cjs} +51 -15
  134. package/dist/src/evalResult-DqzsS6_W.js +3 -0
  135. package/dist/src/{evalResult-D3hVYFis.js → evalResult-eUkJv9Ko.js} +40 -15
  136. package/dist/src/evaluator-DNdJF1Gv.js +3 -0
  137. package/dist/src/{evaluator-IvuDYSvQ.js → evaluator-DRoiYB2q.js} +1060 -187
  138. package/dist/src/evaluatorHelpers-BsYP_muT.js +511 -0
  139. package/dist/src/evaluatorHelpers-CRqTvSux.cjs +537 -0
  140. package/dist/src/evaluatorHelpers-DuqFFfq7.js +510 -0
  141. package/dist/src/{extractor-CAfTSraf.js → extractor-BR7XAzAL.js} +6 -6
  142. package/dist/src/{extractor-WVPOrH43.cjs → extractor-BdxEtt3J.cjs} +6 -6
  143. package/dist/src/{extractor-DNSeBVOJ.js → extractor-CIW3iN-b.js} +6 -6
  144. package/dist/src/{extractor-Dk6bRWkv.js → extractor-CxRtnaHl.js} +5 -5
  145. package/dist/src/{fetch-B0Z3Oe4k.js → fetch-BufrQtvR.js} +93 -40
  146. package/dist/src/{fetch-BEWnXrrG.js → fetch-DXUnXkVU.js} +89 -40
  147. package/dist/src/{fetch-CJU5ELPa.cjs → fetch-Dw4XZHjj.cjs} +330 -270
  148. package/dist/src/{fetch-Di00EQrc.js → fetch-It34O8Ur.js} +305 -252
  149. package/dist/src/fetch-_YgGd2qv.js +3 -0
  150. package/dist/src/{fileExtensions-bYh77CN8.cjs → fileExtensions-BhdwzYaD.cjs} +24 -1
  151. package/dist/src/{fileExtensions-DnqA1y9x.js → fileExtensions-CXRfY3Ss.js} +12 -2
  152. package/dist/src/{fileExtensions-AWa2ZML4.js → fileExtensions-D4GCJ67J.js} +12 -2
  153. package/dist/src/{formatDuration-DZzPsexs.js → formatDuration-CMVNrYvE.js} +1 -1
  154. package/dist/src/{genaiTracer-yRuxj9-L.cjs → genaiTracer-14nugQQx.cjs} +14 -2
  155. package/dist/src/{genaiTracer-DWdZ28hY.js → genaiTracer-BPVvltoW.js} +2 -2
  156. package/dist/src/{genaiTracer-XnrcgDCe.js → genaiTracer-D18lYzhB.js} +2 -2
  157. package/dist/src/{genaiTracer-COYDi-tC.js → genaiTracer-jJKYsnjc.js} +2 -2
  158. package/dist/src/goat-Ckd3q3AY.js +467 -0
  159. package/dist/src/goat-Qgurm-NP.js +466 -0
  160. package/dist/src/goat-ghadEDdy.js +465 -0
  161. package/dist/src/goat-una6pZGP.cjs +469 -0
  162. package/dist/src/graders-BDT7dif6.js +3 -0
  163. package/dist/src/{graders-eIHhRqoC.js → graders-BGP99PdK.js} +2416 -2224
  164. package/dist/src/{graders-Zy3x0zqX.js → graders-BX0f2tvS.js} +2423 -2226
  165. package/dist/src/{graders-pvbReLLn.js → graders-C0nXU_ZP.js} +1806 -1609
  166. package/dist/src/{graders--zknU_uk.cjs → graders-ClrU2fnd.cjs} +2219 -1949
  167. package/dist/src/hydra-BSNZZm2M.js +543 -0
  168. package/dist/src/hydra-BxdG4nkg.js +541 -0
  169. package/dist/src/hydra-DE4xWwyc.js +542 -0
  170. package/dist/src/hydra-DrJttnvw.cjs +542 -0
  171. package/dist/src/image-B4oBtu6J.js +443 -0
  172. package/dist/src/{image-dnoUgPrC.js → image-BN-hjLL9.js} +4 -4
  173. package/dist/src/{image-9302QVqR.js → image-B_fPIwdg.js} +3 -3
  174. package/dist/src/image-BvUAW344.js +442 -0
  175. package/dist/src/image-Cvjwx1uY.js +442 -0
  176. package/dist/src/{image-De2FBmYV.cjs → image-DfVCGPbI.cjs} +4 -4
  177. package/dist/src/{image-u7-rKnYU.js → image-QzmydkiG.js} +4 -4
  178. package/dist/src/image-X0oY4350.cjs +465 -0
  179. package/dist/src/index.cjs +1689 -558
  180. package/dist/src/index.d.cts +3270 -1624
  181. package/dist/src/index.d.ts +3270 -1624
  182. package/dist/src/index.js +1553 -438
  183. package/dist/src/indirectWebPwn-02ZIghCS.js +259 -0
  184. package/dist/src/indirectWebPwn-BJ22AbQa.cjs +397 -0
  185. package/dist/src/indirectWebPwn-CbjUG0rh.js +385 -0
  186. package/dist/src/indirectWebPwn-CfQJt3gk.cjs +260 -0
  187. package/dist/src/indirectWebPwn-DBQhOjoD.js +260 -0
  188. package/dist/src/indirectWebPwn-OsXnKejv.js +259 -0
  189. package/dist/src/indirectWebPwn-tNx9OZ35.js +385 -0
  190. package/dist/src/indirectWebPwn-uyWdHx04.js +386 -0
  191. package/dist/src/inputVariables-B0qUChbV.js +467 -0
  192. package/dist/src/inputVariables-DUGMb9Ka.js +464 -0
  193. package/dist/src/inputVariables-DXFdi7AI.js +468 -0
  194. package/dist/src/inputVariables-Dq9W-Z3a.cjs +475 -0
  195. package/dist/src/{interactiveCheck-CLERUB0c.js → interactiveCheck-C4QlIuoR.js} +2 -2
  196. package/dist/src/{invariant-BtWWVVhl.js → invariant-B2Rf6avk.js} +1 -1
  197. package/dist/src/{invariant-vgHWClmd.js → invariant-DIYf9sP1.js} +1 -1
  198. package/dist/src/{invariant-kfQ8Bu82.cjs → invariant-QtnLD03y.cjs} +1 -1
  199. package/dist/src/iterative-CpU6i2As.js +490 -0
  200. package/dist/src/iterative-DJQEQpG3.js +491 -0
  201. package/dist/src/iterative-DQBuWM-j.cjs +493 -0
  202. package/dist/src/iterative-FTS4Bz67.js +492 -0
  203. package/dist/src/iterativeImage-BUABMVOA.js +413 -0
  204. package/dist/src/iterativeImage-ByFWkxax.cjs +415 -0
  205. package/dist/src/iterativeImage-BzUapOUi.js +414 -0
  206. package/dist/src/iterativeImage-Doz8mgxF.js +413 -0
  207. package/dist/src/iterativeMeta-B3YiAOc8.js +386 -0
  208. package/dist/src/iterativeMeta-C7APE_P1.js +385 -0
  209. package/dist/src/iterativeMeta-CSS8M6Ds.cjs +385 -0
  210. package/dist/src/iterativeMeta-DgoQ7bLh.js +384 -0
  211. package/dist/src/iterativeTree-B5zxBBSW.js +769 -0
  212. package/dist/src/iterativeTree-CNyIk0Yn.js +768 -0
  213. package/dist/src/iterativeTree-CPMF10ve.cjs +771 -0
  214. package/dist/src/iterativeTree-DvZ7GBwt.js +770 -0
  215. package/dist/src/{knowledgeBase-Dgc7CBWF.js → knowledgeBase-BadkINlJ.js} +24 -10
  216. package/dist/src/{knowledgeBase-RhFPGWDc.js → knowledgeBase-Bi_8sV-H.js} +25 -11
  217. package/dist/src/{knowledgeBase-lm9RXSAm.js → knowledgeBase-CkMljjdg.js} +25 -11
  218. package/dist/src/{knowledgeBase-Bpoe_nLu.cjs → knowledgeBase-DUh34xba.cjs} +25 -11
  219. package/dist/src/{litellm-DRjpcSa7.js → litellm-BKBo0jpC.js} +5 -5
  220. package/dist/src/{litellm-C2kqjxqp.js → litellm-BXyn5kZK.js} +5 -5
  221. package/dist/src/{litellm-p37R1dzQ.js → litellm-CNcfbCfa.js} +4 -4
  222. package/dist/src/{litellm-CoyI4IAl.cjs → litellm-CtAr7bKG.cjs} +5 -5
  223. package/dist/src/{logger-DksKw1Qc.js → logger-BbY6ypFL.js} +2 -2
  224. package/dist/src/{logger-B88EkIn6.js → logger-KD8JjCRJ.js} +2 -2
  225. package/dist/src/{logger-COuQb2xB.cjs → logger-cfNpzI4o.cjs} +13 -55
  226. package/dist/src/{luma-ray-KgTCXrZC.js → luma-ray-BMX1iEB6.js} +5 -5
  227. package/dist/src/{luma-ray-B863CmuZ.js → luma-ray-CR5TSpp4.js} +5 -5
  228. package/dist/src/{luma-ray-BxVKaW2a.cjs → luma-ray-D3FUc2K3.cjs} +9 -8
  229. package/dist/src/{luma-ray-BTTLtqQ8.js → luma-ray-OEMmS1RB.js} +6 -6
  230. package/dist/src/main.js +909 -369
  231. package/dist/src/memoryPoisoning-CM83NWYl.js +107 -0
  232. package/dist/src/memoryPoisoning-D8h9gXJF.js +106 -0
  233. package/dist/src/memoryPoisoning-Dp-btinn.cjs +106 -0
  234. package/dist/src/memoryPoisoning-cLuCoTuJ.js +106 -0
  235. package/dist/src/{messages-BTQz42fn.js → messages-BabO-cX8.js} +273 -17
  236. package/dist/src/{messages-811uVVW5.cjs → messages-DBPir0TQ.cjs} +278 -18
  237. package/dist/src/{messages-zWbkLLHz.js → messages-DGUlSNU7.js} +273 -17
  238. package/dist/src/{messages-MYTQ2TWp.js → messages-vsE_-Lv0.js} +273 -17
  239. package/dist/src/{meteor-DHdzY1Ss.js → meteor--TZYICTI.js} +2 -2
  240. package/dist/src/{meteor-Co1VQ1u5.cjs → meteor-CR226f7Z.cjs} +2 -2
  241. package/dist/src/{meteor-CU5UAE-H.js → meteor-Cl_yd7rJ.js} +2 -2
  242. package/dist/src/{meteor-DuAFv6gF.js → meteor-Dce-_zGQ.js} +1 -1
  243. package/dist/src/mischievousUser-0l8GD7Dp.js +46 -0
  244. package/dist/src/mischievousUser-BUOP9W5r.js +46 -0
  245. package/dist/src/mischievousUser-frFYKxu6.js +47 -0
  246. package/dist/src/mischievousUser-olGgHIVR.cjs +46 -0
  247. package/dist/src/{modelslab-Dk1JAtVo.cjs → modelslab-CNV5bMSk.cjs} +7 -7
  248. package/dist/src/{modelslab-D0erNWKe.js → modelslab-Cogmu4mG.js} +6 -6
  249. package/dist/src/{modelslab-DIq-6y7x.js → modelslab-Dzst7VTU.js} +6 -6
  250. package/dist/src/{modelslab-wu9yi5GE.js → modelslab-EyDczZ5A.js} +7 -7
  251. package/dist/src/{nova-reel-CCFRfeRb.js → nova-reel-BGPNBOMS.js} +6 -6
  252. package/dist/src/{nova-reel-DQrm74ng.js → nova-reel-B_5NKFu1.js} +5 -5
  253. package/dist/src/{nova-reel-gr11WG7f.js → nova-reel-C4eUJGse.js} +5 -5
  254. package/dist/src/{nova-reel-CrLXVKQf.cjs → nova-reel-CjJRxI1X.cjs} +9 -8
  255. package/dist/src/{nova-sonic-BYdp-QLs.js → nova-sonic-BNGmgfFz.js} +4 -4
  256. package/dist/src/{nova-sonic-TDgrlTk7.js → nova-sonic-ChPlh5na.js} +4 -4
  257. package/dist/src/{nova-sonic-B_ZXcUJB.js → nova-sonic-CrV0iaY_.js} +3 -3
  258. package/dist/src/{nova-sonic-i5tUvXKn.cjs → nova-sonic-DuOG9Aun.cjs} +5 -4
  259. package/dist/src/{openai-DhVEmgeZ.js → openai-BMHD2Huo.js} +2 -2
  260. package/dist/src/{openai-URNyItar.cjs → openai-C3uXv8wS.cjs} +2 -2
  261. package/dist/src/{openai-Qsvz25mV.js → openai-CJrsh9n4.js} +2 -2
  262. package/dist/src/{openai-iYtrXzOX.js → openai-zgwBb4Ff.js} +1 -1
  263. package/dist/src/{openclaw-CnQ363Wi.js → openclaw-BIHlu_36.js} +10 -8
  264. package/dist/src/{openclaw-CwzlQSQX.js → openclaw-CF7fMido.js} +9 -7
  265. package/dist/src/{openclaw-wX9rtfke.cjs → openclaw-Dphc01BY.cjs} +18 -15
  266. package/dist/src/{openclaw-CLWrW03k.js → openclaw-zIJAsz3P.js} +10 -8
  267. package/dist/src/{opencode-sdk-BUu5Nevv.js → opencode-sdk-B3vlPLsp.js} +40 -5
  268. package/dist/src/{opencode-sdk-BxD8vXp_.js → opencode-sdk-D05JSgMQ.js} +40 -5
  269. package/dist/src/{opencode-sdk-BZ2idgYA.cjs → opencode-sdk-DoY6GbWw.cjs} +46 -10
  270. package/dist/src/{opencode-sdk-GI2KaAXq.js → opencode-sdk-sRKYHGoI.js} +39 -4
  271. package/dist/src/{otlpReceiver-BntK801g.js → otlpReceiver--gTpSagc.js} +120 -4
  272. package/dist/src/{otlpReceiver-DmVulbhC.js → otlpReceiver-B2eaKC8C.js} +120 -4
  273. package/dist/src/{otlpReceiver-B2z58l4e.js → otlpReceiver-BXjcRqAM.js} +119 -3
  274. package/dist/src/{otlpReceiver-BfcVq2Nq.cjs → otlpReceiver-CvJdBGSc.cjs} +125 -7
  275. package/dist/src/packageParser--MWTSrPW.js +36 -0
  276. package/dist/src/packageParser-CgE-ziRo.js +35 -0
  277. package/dist/src/packageParser-QoCS1FMl.cjs +54 -0
  278. package/dist/src/packageParser-hwwSGnAZ.js +35 -0
  279. package/dist/src/processShim-BBxt7LKO.js +95 -0
  280. package/dist/src/processShim-BcGzU8fY.js +94 -0
  281. package/dist/src/processShim-C_z3aRvF.js +94 -0
  282. package/dist/src/processShim-DSY9BV2T.cjs +98 -0
  283. package/dist/src/promptLength-0qIHyhA5.js +71 -0
  284. package/dist/src/promptLength-4X-Wd8PG.js +72 -0
  285. package/dist/src/promptLength-B9nZEfO6.js +71 -0
  286. package/dist/src/promptLength-BbBbDHNj.cjs +94 -0
  287. package/dist/src/promptfoo-BDrfT30-.js +180 -0
  288. package/dist/src/promptfoo-Cm4hiy1Y.js +180 -0
  289. package/dist/src/promptfoo-Rjp-MeBb.js +181 -0
  290. package/dist/src/promptfoo-b-baRMj-.cjs +205 -0
  291. package/dist/src/prompts-BYMtqPCw.js +259 -0
  292. package/dist/src/prompts-C-bqE1Yp.js +260 -0
  293. package/dist/src/prompts-Cp_Qx5Ml.js +270 -0
  294. package/dist/src/prompts-DHhQsANy.js +259 -0
  295. package/dist/src/prompts-D_QpZ2Dm.js +271 -0
  296. package/dist/src/prompts-hNvWBD3z.cjs +284 -0
  297. package/dist/src/prompts-huDVH2CI.js +270 -0
  298. package/dist/src/prompts-p78Hul5i.cjs +289 -0
  299. package/dist/src/{providerRegistry-CPQ_CmVO.js → providerRegistry-1gB5vtzQ.js} +2 -2
  300. package/dist/src/{providerRegistry-CQMdTmHP.cjs → providerRegistry-CZO_w7ue.cjs} +2 -2
  301. package/dist/src/{providerRegistry-Bvh8mv85.js → providerRegistry-DHcFiVWX.js} +1 -1
  302. package/dist/src/{providerRegistry-CWoPjKFZ.js → providerRegistry-ReCd0sFa.js} +2 -2
  303. package/dist/src/{providers-BV_KMZje.js → providers-B9KzWxAX.js} +10558 -21587
  304. package/dist/src/{providers-DruaQfwu.js → providers-BCCz6_IX.js} +1228 -12196
  305. package/dist/src/{providers-1eKkXBKp.cjs → providers-BDVVIQM6.cjs} +10649 -21843
  306. package/dist/src/{providers-iUt5fbAN.js → providers-BYAn82cf.js} +1 -1
  307. package/dist/src/{providers-Domz_llv.js → providers-DVYRZP4E.js} +10589 -21570
  308. package/dist/src/{pythonUtils-Cldx7huE.js → pythonUtils-CLCgQ9tt.js} +3 -3
  309. package/dist/src/{pythonUtils-CnndUbW-.js → pythonUtils-CgYxeSmO.js} +3 -3
  310. package/dist/src/{pythonUtils-tAJvvpS-.cjs → pythonUtils-Cokhluq3.cjs} +8 -7
  311. package/dist/src/{pythonUtils-C2UQ30Rz.js → pythonUtils-D0BYebvX.js} +3 -3
  312. package/dist/src/{quiverai-DFotyafY.cjs → quiverai-BAp6iTZD.cjs} +4 -4
  313. package/dist/src/{quiverai-aPPvXOgn.js → quiverai-BvIhI_0l.js} +4 -4
  314. package/dist/src/{quiverai-DR0SnIQV.js → quiverai-CdTWPe-A.js} +3 -3
  315. package/dist/src/{quiverai-CtWi6x_g.js → quiverai-Cv7rJKDz.js} +4 -4
  316. package/dist/src/registry-BUJrgjwv.js +124 -0
  317. package/dist/src/registry-DXm1t_x0.js +125 -0
  318. package/dist/src/registry-Dp5EqoXc.js +124 -0
  319. package/dist/src/registry-KCVF1CFC.cjs +124 -0
  320. package/dist/src/{server-D6Il2Sob.js → remoteGeneration-B1_XsKXU.js} +16 -108
  321. package/dist/src/{server-BSB45Nt9.js → remoteGeneration-COpWcmWd.js} +15 -146
  322. package/dist/src/{server-Dx2TyCH2.cjs → remoteGeneration-DS9N3pgB.cjs} +30 -119
  323. package/dist/src/remoteGeneration-DsaSwmG2.js +217 -0
  324. package/dist/src/render-BNTrbmBw.cjs +384 -0
  325. package/dist/src/render-CSP99NLm.js +348 -0
  326. package/dist/src/render-DFfDeYUK.js +347 -0
  327. package/dist/src/{render-CgVDrJmM.js → render-DznWrxGO.js} +2 -2
  328. package/dist/src/render-_6ur1fhE.js +347 -0
  329. package/dist/src/resourceAttributes-D1jP3kL5.js +17 -0
  330. package/dist/src/resourceAttributes-DQbBB--2.js +16 -0
  331. package/dist/src/resourceAttributes-ephgOvdR.cjs +27 -0
  332. package/dist/src/resourceAttributes-v6-I67fn.js +16 -0
  333. package/dist/src/{responses-Bi9vBuW_.cjs → responses-1UFFF9N_.cjs} +51 -16
  334. package/dist/src/{responses-DL9m8CyY.js → responses-B3W2JvOQ.js} +49 -15
  335. package/dist/src/{responses--OsX2aYW.js → responses-B6ktc3Ra.js} +49 -15
  336. package/dist/src/{responses-C-flexAY.js → responses-URRzV8qE.js} +49 -15
  337. package/dist/src/rolldown-runtime-D_mwlA32.cjs +43 -0
  338. package/dist/src/rubyUtils-BYVlQ94c.js +3 -0
  339. package/dist/src/{rubyUtils-DsGrTx8R.js → rubyUtils-CXlFM2rR.js} +3 -3
  340. package/dist/src/{rubyUtils-DVLeA2jg.js → rubyUtils-CnlW8AYb.js} +3 -3
  341. package/dist/src/{rubyUtils-B6eljPuh.cjs → rubyUtils-CqUWBZAt.cjs} +18 -27
  342. package/dist/src/{rubyUtils-CYSQEG4a.js → rubyUtils-DdGojpfv.js} +3 -3
  343. package/dist/src/runtimeTransform-BJOpL9Yc.js +142 -0
  344. package/dist/src/runtimeTransform-Dgh_D7DU.js +143 -0
  345. package/dist/src/runtimeTransform-DigbjU1r.js +142 -0
  346. package/dist/src/runtimeTransform-ON3YYILw.cjs +147 -0
  347. package/dist/src/{sagemaker-BVkaG2-l.js → sagemaker-CujrzP1a.js} +62 -51
  348. package/dist/src/{sagemaker-XnfhheQv.cjs → sagemaker-DzffAqo_.cjs} +65 -53
  349. package/dist/src/{sagemaker-D67yzMzs.js → sagemaker-vhtSV7JI.js} +62 -51
  350. package/dist/src/{sagemaker-BveBvuxm.js → sagemaker-yr1QKeBs.js} +61 -50
  351. package/dist/src/{scanner-1DqWi1Ej.js → scanner-DS0109SS.js} +7 -7
  352. package/dist/src/server/index.js +5105 -605
  353. package/dist/src/server-B8rqV126.cjs +126 -0
  354. package/dist/src/server-BaLytskk.js +3 -0
  355. package/dist/src/server-CMJD10J4.js +107 -0
  356. package/dist/src/server-Ddp8GNMp.js +146 -0
  357. package/dist/src/server-DhMHosWj.js +182 -0
  358. package/dist/src/shared-7pmVZLNO.js +1334 -0
  359. package/dist/src/shared-9WHQ1oNE.js +1335 -0
  360. package/dist/src/{fileExtensions-BArZuxsI.js → shared-BoG7qLMv.js} +12 -2
  361. package/dist/src/shared-D6IjElRI.js +1334 -0
  362. package/dist/src/shared-WkgnDkcg.cjs +1436 -0
  363. package/dist/src/{signal-CE5G3a7x.js → signal-CSurUUyV.js} +3 -3
  364. package/dist/src/simulatedUser-C9aQObBI.js +222 -0
  365. package/dist/src/simulatedUser-Cu601Dd4.cjs +227 -0
  366. package/dist/src/simulatedUser-U_qAHnuB.js +222 -0
  367. package/dist/src/simulatedUser-p3tACcmw.js +223 -0
  368. package/dist/src/{slack-DDUe-5MC.js → slack-Bapo-7_8.js} +2 -2
  369. package/dist/src/{slack-1Rhq0EoV.cjs → slack-DMC1QVEg.cjs} +3 -2
  370. package/dist/src/{slack-D5Wpy8LM.js → slack-DTEFhrMn.js} +2 -2
  371. package/dist/src/{slack-acRb0IqQ.js → slack-k-_CP84Q.js} +1 -1
  372. package/dist/src/storage-BU4qcnOb.js +875 -0
  373. package/dist/src/storage-CA-v9V2v.cjs +911 -0
  374. package/dist/src/storage-CD-GWAdx.js +822 -0
  375. package/dist/src/storage-QdU-SmvD.js +834 -0
  376. package/dist/src/{store-DAAyxcy6.cjs → store-B2NDDooM.cjs} +60 -24
  377. package/dist/src/{store-CYEy5J2D.js → store-DKd5592Q.js} +51 -20
  378. package/dist/src/{store-M0b1WfYb.js → store-HpopRVzl.js} +50 -19
  379. package/dist/src/store-IbiRIF3k.js +3 -0
  380. package/dist/src/strategies-7CS3Alao.cjs +2360 -0
  381. package/dist/src/strategies-CiSeroPH.js +2331 -0
  382. package/dist/src/strategies-DRJjGTIY.js +2333 -0
  383. package/dist/src/{tables-DQ4WU5tX.js → tables-CRSXQ2Ke.js} +2 -2
  384. package/dist/src/{tables-CsWou1Bx.js → tables-CxjU7bBd.js} +3 -3
  385. package/dist/src/{tables-DUfh1F7Z.cjs → tables-DBIJU0WE.cjs} +6 -5
  386. package/dist/src/{tables-C4CH3zRr.js → tables-DafUHOeh.js} +3 -3
  387. package/dist/src/{telemetry-CQPez_Jp.js → telemetry-00ezXr_t.js} +5 -4
  388. package/dist/src/telemetry-ByPqDcKC.js +3 -0
  389. package/dist/src/{telemetry-Dsw_faFj.cjs → telemetry-CJ7FnCsc.cjs} +18 -11
  390. package/dist/src/{telemetry-dbaJ0E98.js → telemetry-DmXYcJNV.js} +5 -4
  391. package/dist/src/{telemetry-Dvqxv3YC.js → telemetry-DwX9XUN5.js} +4 -3
  392. package/dist/src/{text-KvuD2Iko.js → text-Db-Wt2u2.js} +1 -1
  393. package/dist/src/{text-DHxdyQqT.js → text-DwYK5EBn.js} +1 -1
  394. package/dist/src/{text-BVi-cLPJ.cjs → text-nywWsRBM.cjs} +1 -1
  395. package/dist/src/{tokenUsageUtils-C-bmyHoE.js → tokenUsageUtils-BjVkdk18.js} +1 -1
  396. package/dist/src/{tokenUsageUtils-CXrvO-wA.js → tokenUsageUtils-CDet74yk.js} +1 -1
  397. package/dist/src/tokenUsageUtils-CmnQ0G2m.js +142 -0
  398. package/dist/src/{tokenUsageUtils-Bb7DkZPz.cjs → tokenUsageUtils-_B-P8IAi.cjs} +1 -1
  399. package/dist/src/toolAttributes-BAjwcBf0.cjs +103 -0
  400. package/dist/src/toolAttributes-COVgDrBG.js +87 -0
  401. package/dist/src/toolAttributes-DJ9ZEKXD.js +86 -0
  402. package/dist/src/tracingOptions-BnwKCkSB.js +221 -0
  403. package/dist/src/tracingOptions-Chi74lOD.js +219 -0
  404. package/dist/src/tracingOptions-DrbSFaKy.cjs +249 -0
  405. package/dist/src/tracingOptions-ji2OuXbT.js +220 -0
  406. package/dist/src/{transcription-DuWDupG7.js → transcription-B8uIgCYX.js} +5 -5
  407. package/dist/src/{transcription-CJspiD2c.js → transcription-CfU5loSq.js} +6 -6
  408. package/dist/src/{transcription-V2HaAmy2.js → transcription-Dkd22_4K.js} +6 -6
  409. package/dist/src/{transcription-BvjmiYB1.cjs → transcription-mzuf18Mq.cjs} +9 -8
  410. package/dist/src/{transform-lQrDE1BQ.js → transform-BIMynQsA.js} +9 -9
  411. package/dist/src/transform-BnSTnFlp.js +187 -0
  412. package/dist/src/transform-BnSXWmU_2.cjs +221 -0
  413. package/dist/src/transform-CGt7Kt3y2.js +186 -0
  414. package/dist/src/transform-CrPGTsij.js +186 -0
  415. package/dist/src/{transform-CTeuTR3S.cjs → transform-DhNkAUs8.cjs} +13 -12
  416. package/dist/src/{transform-CG0ehZNG.js → transform-DmvYBRll.js} +9 -9
  417. package/dist/src/{transform-zDhMmzwX.js → transform-EtD4jAWi.js} +9 -9
  418. package/dist/src/{transformersAvailability-CcHusyhw.js → transformersAvailability-0ThtPved.js} +1 -1
  419. package/dist/src/transformersAvailability-BYydDE5U.js +35 -0
  420. package/dist/src/{transformersAvailability-DLlROWhg.js → transformersAvailability-BvyU9vDD.js} +1 -1
  421. package/dist/src/{transformersAvailability-Cju9mHgR.cjs → transformersAvailability-BytPvKUW.cjs} +1 -1
  422. package/dist/src/{types-Dm9JM6Vb.js → types-BFevViUY.js} +115 -19
  423. package/dist/src/{types-Bgh5SOn6.js → types-BJQBBPTP.js} +115 -19
  424. package/dist/src/{types-CeaeaZdP.cjs → types-CxJvaY2S.cjs} +357 -172
  425. package/dist/src/{types-BGQDAP8i.js → types-D6glLbdF.js} +271 -170
  426. package/dist/src/{util-BYvQUPp7.js → util--WMgw7wM.js} +28 -8
  427. package/dist/src/{util-C9J8ahRn.js → util-5WnCSb0h.js} +72 -48
  428. package/dist/src/{util-CN3SrLT4.cjs → util-BSIuSLVK.cjs} +74 -49
  429. package/dist/src/{util-C8e5uydV.js → util-Bx677_k2.js} +154 -147
  430. package/dist/src/util-CN8om2rz.cjs +386 -0
  431. package/dist/src/{util-DDs-7g6-.js → util-CoQWM76y.js} +28 -8
  432. package/dist/src/util-DNl96nNs.js +327 -0
  433. package/dist/src/{util-DxWpWjhc.js → util-DURocbYR.js} +667 -507
  434. package/dist/src/util-Df8YMvS1.js +327 -0
  435. package/dist/src/{util-DvU2Pw8c.js → util-DiQ3QvBB.js} +28 -8
  436. package/dist/src/{util-oGMLA7vc.js → util-I-Rf-KaD.js} +862 -577
  437. package/dist/src/{util-olYL5C6N.cjs → util-IYzs5Y04.cjs} +33 -7
  438. package/dist/src/{util-D9TisOyk.js → util-LKTmNsMQ.js} +71 -47
  439. package/dist/src/{util-Bxn8emtE.cjs → util-SPsvFONY.cjs} +738 -582
  440. package/dist/src/{util-D3q0WQ-0.js → util-efByNxcr.js} +72 -48
  441. package/dist/src/util-kDURhgJW.js +328 -0
  442. package/dist/src/{utils-DJfvjyMj.js → utils-B0lzitHZ.js} +3 -3
  443. package/dist/src/{utils-BLJKfv0y.js → utils-BFOh20Gb.js} +3 -3
  444. package/dist/src/{utils-hXtCYanr.js → utils-BGY69tk_.js} +2 -2
  445. package/dist/src/{utils-B05gLxER.cjs → utils-Ve6kuJsa.cjs} +3 -3
  446. package/dist/src/version-BK20a4sw.js +16 -0
  447. package/dist/src/version-BWCSaByA.cjs +27 -0
  448. package/dist/src/version-eRkNuGv8.js +17 -0
  449. package/dist/src/version-lpHV_53E.js +16 -0
  450. package/dist/tsconfig.tsbuildinfo +1 -1
  451. package/package.json +56 -28
  452. package/dist/src/app/assets/Report-CQYFezYu.js +0 -1
  453. package/dist/src/app/assets/index-BXGkeMwh.css +0 -1
  454. package/dist/src/app/assets/index-BzJt18Jz.js +0 -385
  455. package/dist/src/app/assets/sync-IjzpWrOE.js +0 -4
  456. package/dist/src/app/assets/vendor-charts-BNdH8TCw.js +0 -36
  457. package/dist/src/cache-Cr9oLMUa.js +0 -3
  458. package/dist/src/cache-DbLsVWB2.cjs +0 -3
  459. package/dist/src/cloud-Hphvo8kr.js +0 -3
  460. package/dist/src/codex-sdk-BAmYE7qy.js +0 -3
  461. package/dist/src/codex-sdk-CWEnH70W.cjs +0 -2
  462. package/dist/src/evalResult-D8MT9p0s.js +0 -3
  463. package/dist/src/evalResult-DElBuddX.js +0 -2
  464. package/dist/src/evalResult-Dvc-iucu.cjs +0 -2
  465. package/dist/src/evaluator-CVessDWe.js +0 -3
  466. package/dist/src/fetch-C7bGKDlQ.js +0 -3
  467. package/dist/src/graders-BOAzQEUe.cjs +0 -2
  468. package/dist/src/graders-D4BTsZdG2.js +0 -3
  469. package/dist/src/graders-DOJK1XpV.js +0 -2
  470. package/dist/src/graders-NAv9LcBn.js +0 -2
  471. package/dist/src/image-B5Mv-Z3h.js +0 -257
  472. package/dist/src/image-DVz2RiMF.js +0 -258
  473. package/dist/src/image-qUpPvmNZ.js +0 -257
  474. package/dist/src/image-x6KqLQl4.cjs +0 -280
  475. package/dist/src/providers-Bp4S-FvO.js +0 -2
  476. package/dist/src/providers-DV3ax9e_.cjs +0 -3
  477. package/dist/src/providers-u9Enmfok.js +0 -2
  478. package/dist/src/render-CH-62LbA.js +0 -135
  479. package/dist/src/render-CMEpfLaO.js +0 -136
  480. package/dist/src/render-DHIZ6_k8.js +0 -135
  481. package/dist/src/render-DfQSFxGE.cjs +0 -165
  482. package/dist/src/rubyUtils-D1L2d3jb.js +0 -3
  483. package/dist/src/rubyUtils-DUbq4tff.cjs +0 -2
  484. package/dist/src/server-BNYztJkh.js +0 -385
  485. package/dist/src/server-DCtHUqlp.js +0 -3
  486. package/dist/src/server-DaA2eR26.cjs +0 -2
  487. package/dist/src/store-CWOSz6D_.cjs +0 -2
  488. package/dist/src/store-DCDBhv7B.js +0 -3
  489. package/dist/src/store-Dn9HUkdW.js +0 -240
  490. package/dist/src/telemetry-C1IqxcdW.js +0 -3
  491. package/dist/src/telemetry-C4ZEa_es.cjs +0 -2
  492. package/dist/src/transform-Bbg6A8Jk.js +0 -216
  493. package/dist/src/transform-CUnzlsbn.cjs +0 -228
  494. package/dist/src/transform-DYX1_Xnh.js +0 -216
  495. package/dist/src/transform-DgKlRr73.cjs +0 -2
  496. package/dist/src/transform-M6ITAESf.js +0 -3
  497. package/dist/src/transform-UN5UGu8U.js +0 -213
@@ -1,14 +1,16 @@
1
1
  #!/usr/bin/env node
2
- import { N as state, T as getEnvBool, m as sanitizeObject, s as logger } from "./logger-DksKw1Qc.js";
3
- import { F as VERSION, k as TERMINAL_MAX_WIDTH, n as fetchWithProxy } from "./fetch-BEWnXrrG.js";
4
- import { t as invariant } from "./invariant-BtWWVVhl.js";
5
- import { m as isProviderOptions, o as OutputFileExtension, p as isApiProvider, s as ResultFailureReason } from "./types-Dm9JM6Vb.js";
6
- import { o as safeResolve, r as importModule, t as getDirectory } from "./esm-tVgYPY-f.js";
7
- import { a as getNunjucksEngine, n as renderVarsInObject } from "./render-CMEpfLaO.js";
8
- import { i as isJavascriptFile, t as JAVASCRIPT_EXTENSIONS } from "./fileExtensions-AWa2ZML4.js";
9
- import { r as runPython } from "./pythonUtils-CnndUbW-.js";
2
+ import { N as state, T as getEnvBool, m as sanitizeObject, s as logger } from "./logger-BbY6ypFL.js";
3
+ import { M as TERMINAL_MAX_WIDTH, n as fetchWithProxy } from "./fetch-DXUnXkVU.js";
4
+ import { n as VERSION } from "./version-eRkNuGv8.js";
5
+ import { t as invariant } from "./invariant-B2Rf6avk.js";
6
+ import { m as isProviderOptions, o as OutputFileExtension, p as isApiProvider, s as ResultFailureReason } from "./types-BFevViUY.js";
7
+ import { i as isJavascriptFile, t as JAVASCRIPT_EXTENSIONS } from "./fileExtensions-D4GCJ67J.js";
8
+ import { o as safeResolve, r as importModule, t as getDirectory } from "./esm-Bexx2PFc.js";
9
+ import { n as renderVarsInObject, o as getNunjucksEngine } from "./render-CSP99NLm.js";
10
+ import { r as runPython } from "./pythonUtils-CgYxeSmO.js";
10
11
  import dotenv from "dotenv";
11
12
  import * as fs$2 from "fs";
13
+ import fs from "fs";
12
14
  import * as path$1 from "path";
13
15
  import path from "path";
14
16
  import * as os$1 from "os";
@@ -21,309 +23,6 @@ import { parse as parse$1 } from "csv-parse/sync";
21
23
  import { globSync, hasMagic } from "glob";
22
24
  import { XMLBuilder } from "fast-xml-parser";
23
25
  import { stringify } from "csv-stringify/sync";
24
- //#region src/util/provider.ts
25
- function canonicalizeProviderId(id) {
26
- if (id.startsWith("file://")) {
27
- const filePath = id.slice(7);
28
- return path$1.isAbsolute(filePath) ? id : `file://${path$1.resolve(filePath)}`;
29
- }
30
- for (const prefix of [
31
- "exec:",
32
- "python:",
33
- "golang:"
34
- ]) if (id.startsWith(prefix)) {
35
- const filePath = id.slice(prefix.length);
36
- if (filePath.includes("/") || filePath.includes("\\")) return `${prefix}${path$1.resolve(filePath)}`;
37
- return id;
38
- }
39
- if ((id.endsWith(".js") || id.endsWith(".ts") || id.endsWith(".mjs")) && (id.includes("/") || id.includes("\\"))) return `file://${path$1.resolve(id)}`;
40
- return id;
41
- }
42
- function getProviderLabel(provider) {
43
- return provider?.label && typeof provider.label === "string" ? provider.label : void 0;
44
- }
45
- function providerToIdentifier(provider) {
46
- if (!provider) return;
47
- if (typeof provider === "string") return canonicalizeProviderId(provider);
48
- const label = getProviderLabel(provider);
49
- if (label) return label;
50
- if (isApiProvider(provider)) return canonicalizeProviderId(provider.id());
51
- if (isProviderOptions(provider)) {
52
- if (provider.id) return canonicalizeProviderId(provider.id);
53
- return;
54
- }
55
- if (typeof provider === "object" && "id" in provider && typeof provider.id === "string") return canonicalizeProviderId(provider.id);
56
- }
57
- /**
58
- * Gets a descriptive identifier string for a provider, showing both label and ID when both exist.
59
- * Useful for error messages to help users debug provider reference issues.
60
- */
61
- function getProviderDescription(provider) {
62
- const label = provider.label;
63
- const id = provider.id();
64
- if (label && label !== id) return `${label} (${id})`;
65
- return id;
66
- }
67
- /**
68
- * Checks if a provider reference matches a given provider.
69
- * Supports exact matching and wildcard patterns.
70
- */
71
- function doesProviderRefMatch(ref, provider) {
72
- const label = provider.label;
73
- const id = provider.id();
74
- const canonicalRef = canonicalizeProviderId(ref);
75
- const canonicalId = canonicalizeProviderId(id);
76
- if (label && label === ref) return true;
77
- if (id === ref || canonicalId === canonicalRef) return true;
78
- if (ref.endsWith("*")) {
79
- const prefix = ref.slice(0, -1);
80
- if (label?.startsWith(prefix) || id.startsWith(prefix) || canonicalId.startsWith(prefix)) return true;
81
- }
82
- if (label?.startsWith(`${ref}:`) || id.startsWith(`${ref}:`) || canonicalId.startsWith(`${ref}:`)) return true;
83
- return false;
84
- }
85
- /**
86
- * Checks if a provider is allowed based on a list of allowed references.
87
- */
88
- function isProviderAllowed(provider, allowedProviders) {
89
- if (!Array.isArray(allowedProviders)) return true;
90
- if (allowedProviders.length === 0) return false;
91
- return allowedProviders.some((ref) => doesProviderRefMatch(ref, provider));
92
- }
93
- /**
94
- * Detects if a provider uses OpenAI models.
95
- * This includes direct OpenAI providers and Azure OpenAI.
96
- */
97
- function isOpenAiProvider(providerId) {
98
- const lowerProviderId = providerId.toLowerCase();
99
- if (lowerProviderId.startsWith("openai:")) return true;
100
- if (lowerProviderId.startsWith("azureopenai:")) return true;
101
- if (lowerProviderId.startsWith("azure:")) {
102
- if ([
103
- "gpt",
104
- "openai",
105
- "davinci",
106
- "curie",
107
- "babbage",
108
- "ada",
109
- "text-embedding",
110
- "whisper",
111
- "dall-e",
112
- "tts"
113
- ].some((indicator) => lowerProviderId.includes(indicator))) return true;
114
- }
115
- return false;
116
- }
117
- /**
118
- * Detects if a provider uses Anthropic/Claude models.
119
- * This includes direct Anthropic providers, Bedrock with Claude, and Vertex with Claude.
120
- */
121
- function isAnthropicProvider(providerId) {
122
- const lowerProviderId = providerId.toLowerCase();
123
- if (lowerProviderId.startsWith("anthropic:")) return true;
124
- if (lowerProviderId.startsWith("bedrock:")) {
125
- if (lowerProviderId.includes("claude") || lowerProviderId.includes("anthropic")) return true;
126
- }
127
- if (lowerProviderId.startsWith("vertex:")) {
128
- if (lowerProviderId.includes("claude")) return true;
129
- }
130
- return false;
131
- }
132
- const KNOWN_ENV_VARS = {
133
- openai: "OPENAI_API_KEY",
134
- anthropic: "ANTHROPIC_API_KEY",
135
- google: "GOOGLE_API_KEY",
136
- mistral: "MISTRAL_API_KEY",
137
- cohere: "COHERE_API_KEY",
138
- replicate: "REPLICATE_API_TOKEN",
139
- voyage: "VOYAGE_API_KEY",
140
- ai21: "AI21_API_KEY",
141
- xai: "XAI_API_KEY",
142
- groq: "GROQ_API_KEY",
143
- deepseek: "DEEPSEEK_API_KEY",
144
- perplexity: "PERPLEXITY_API_KEY",
145
- hyperbolic: "HYPERBOLIC_API_KEY",
146
- cerebras: "CEREBRAS_API_KEY",
147
- togetherai: "TOGETHER_API_KEY",
148
- fal: "FAL_KEY",
149
- huggingface: "HF_TOKEN",
150
- "cloudflare-ai": "CLOUDFLARE_API_KEY"
151
- };
152
- function getDefaultEnvVar(providerId) {
153
- const prefix = providerId.split(":")[0];
154
- return KNOWN_ENV_VARS[prefix] || `${prefix.toUpperCase()}_API_KEY`;
155
- }
156
- /**
157
- * Pre-checks providers for missing API keys before evaluation starts.
158
- * Assumes getApiKey() is side-effect free (no network calls or token refresh).
159
- */
160
- function checkProviderApiKeys(providers) {
161
- const missingApiKeys = /* @__PURE__ */ new Map();
162
- for (const provider of providers) {
163
- const p = provider;
164
- if (typeof p.getApiKey !== "function") continue;
165
- if (provider.id().startsWith("azure:")) continue;
166
- const requiresKey = typeof p.requiresApiKey === "function" ? p.requiresApiKey() : p.config?.apiKeyRequired !== false;
167
- let apiKey;
168
- try {
169
- apiKey = p.getApiKey();
170
- } catch {
171
- apiKey = void 0;
172
- }
173
- if (requiresKey && !apiKey) {
174
- const envVar = p.config?.apiKeyEnvar || getDefaultEnvVar(provider.id());
175
- if (!missingApiKeys.has(envVar)) missingApiKeys.set(envVar, []);
176
- missingApiKeys.get(envVar).push(provider.id());
177
- }
178
- }
179
- return missingApiKeys;
180
- }
181
- /**
182
- * Detects if a provider uses Google models.
183
- * This includes direct Google/Vertex providers with Gemini and other Google models.
184
- * Note: Vertex with Claude models is NOT counted as Google (it's Anthropic).
185
- */
186
- function isGoogleProvider(providerId) {
187
- const lowerProviderId = providerId.toLowerCase();
188
- if (lowerProviderId.startsWith("google:")) return true;
189
- if (lowerProviderId.startsWith("vertex:")) {
190
- if (!lowerProviderId.includes("claude")) return true;
191
- }
192
- return false;
193
- }
194
- //#endregion
195
- //#region src/util/comparison.ts
196
- /**
197
- * Explicit runtime variable names that don't follow the underscore convention.
198
- * These are added during evaluation but aren't part of the original test definition.
199
- *
200
- * - sessionId: Added by multi-turn strategy providers (GOAT, Crescendo)
201
- *
202
- * Note: Variables starting with underscore (e.g., _conversation) are automatically
203
- * treated as runtime variables and filtered out.
204
- */
205
- const EXPLICIT_RUNTIME_VAR_KEYS = ["sessionId"];
206
- /**
207
- * Checks if a variable key is a runtime-only variable that should be filtered
208
- * when comparing test cases.
209
- *
210
- * Runtime variables are identified by:
211
- * 1. Starting with underscore (_) - convention for internal/runtime vars
212
- * 2. Being in the explicit runtime var list (for legacy vars like sessionId)
213
- */
214
- function isRuntimeVar(key) {
215
- return key.startsWith("_") || EXPLICIT_RUNTIME_VAR_KEYS.includes(key);
216
- }
217
- /**
218
- * Filters out runtime-only variables that are added during evaluation
219
- * but aren't part of the original test definition.
220
- *
221
- * This is used when comparing test cases to determine if a result
222
- * corresponds to a particular test, regardless of runtime state.
223
- *
224
- * Runtime variables are identified by:
225
- * - Starting with underscore (e.g., _conversation, _metadata)
226
- * - Being in the explicit list (e.g., sessionId for backward compatibility)
227
- */
228
- function filterRuntimeVars(vars) {
229
- if (!vars || typeof vars !== "object" || Array.isArray(vars)) return vars;
230
- const filtered = {};
231
- for (const [key, value] of Object.entries(vars)) if (!isRuntimeVar(key)) filtered[key] = value;
232
- return filtered;
233
- }
234
- /**
235
- * Extracts only runtime variables from a vars object.
236
- * This is the inverse of filterRuntimeVars.
237
- *
238
- * Used to restore runtime state when re-running filtered tests.
239
- */
240
- function extractRuntimeVars(vars) {
241
- if (!vars || typeof vars !== "object" || Array.isArray(vars)) return;
242
- const extracted = {};
243
- for (const [key, value] of Object.entries(vars)) if (isRuntimeVar(key)) extracted[key] = value;
244
- return Object.keys(extracted).length > 0 ? extracted : void 0;
245
- }
246
- function varsMatch(vars1, vars2) {
247
- return deepEqual(vars1, vars2);
248
- }
249
- /**
250
- * Generate a unique key for a test case for deduplication purposes.
251
- * Excludes runtime variables and includes strategyId to distinguish tests
252
- * with the same prompt but different strategies.
253
- *
254
- * @param testCase - The test case to generate a key for
255
- * @returns A JSON string that uniquely identifies the test case
256
- */
257
- function getTestCaseDeduplicationKey(testCase) {
258
- const filteredVars = filterRuntimeVars(testCase.vars);
259
- const strategyId = testCase.metadata?.strategyId || "none";
260
- return JSON.stringify({
261
- vars: filteredVars,
262
- strategyId
263
- });
264
- }
265
- /**
266
- * Deduplicates an array of test cases based on their vars and strategyId.
267
- * Tests with the same vars but different strategies are considered different.
268
- * Runtime variables (like _conversation, sessionId) are filtered out before comparison.
269
- *
270
- * @param tests - Array of test cases to deduplicate
271
- * @returns Deduplicated array of test cases
272
- */
273
- function deduplicateTestCases(tests) {
274
- const seen = /* @__PURE__ */ new Set();
275
- return tests.filter((test) => {
276
- const key = getTestCaseDeduplicationKey(test);
277
- if (seen.has(key)) return false;
278
- seen.add(key);
279
- return true;
280
- });
281
- }
282
- function resultIsForTestCase(result, testCase) {
283
- const testProviderId = testCase.provider ? providerToIdentifier(testCase.provider) : void 0;
284
- const resultProviderId = providerToIdentifier(result.provider);
285
- const providersMatch = !testProviderId || !resultProviderId || testProviderId === resultProviderId;
286
- const resultVars = filterRuntimeVars(result.vars);
287
- const testVars = filterRuntimeVars(testCase.vars);
288
- const doVarsMatch = varsMatch(testVars, resultVars);
289
- const isMatch = doVarsMatch && providersMatch;
290
- if (!isMatch) {
291
- const varKeys = testVars ? Object.keys(testVars).join(", ") : "none";
292
- logger.debug(`[resultIsForTestCase] No match: vars=${doVarsMatch}, providers=${providersMatch}`, {
293
- testProvider: testProviderId || "none",
294
- resultProvider: resultProviderId || "none",
295
- testVarKeys: varKeys
296
- });
297
- }
298
- return isMatch;
299
- }
300
- //#endregion
301
- //#region src/util/env.ts
302
- /**
303
- * Load environment variables from .env file(s).
304
- * @param envPath - Single path, array of paths, or undefined for default .env loading.
305
- * When paths are explicitly specified, all files must exist or an error is thrown.
306
- * When multiple files are provided, later files override values from earlier files.
307
- */
308
- function setupEnv(envPath) {
309
- if (envPath) {
310
- const paths = (Array.isArray(envPath) ? envPath : [envPath]).flatMap((p) => p.includes(",") ? p.split(",").map((s) => s.trim()) : p.trim()).filter((p) => p.length > 0);
311
- if (paths.length === 0) {
312
- dotenv.config({ quiet: true });
313
- return;
314
- }
315
- for (const p of paths) if (!fs$2.existsSync(p)) throw new Error(`Environment file not found: ${p}`);
316
- if (paths.length === 1) logger.info(`Loading environment variables from ${paths[0]}`);
317
- else logger.info(`Loading environment variables from: ${paths.join(", ")}`);
318
- const pathArg = paths.length === 1 ? paths[0] : paths;
319
- dotenv.config({
320
- path: pathArg,
321
- override: true,
322
- quiet: true
323
- });
324
- } else dotenv.config({ quiet: true });
325
- }
326
- //#endregion
327
26
  //#region src/util/functions/loadFunction.ts
328
27
  const functionCache = {};
329
28
  /**
@@ -448,243 +147,676 @@ function maybeLoadFromExternalFile(filePath, context) {
448
147
  else allContents.push(...records);
449
148
  } else allContents.push(contents);
450
149
  }
451
- return allContents;
150
+ return allContents;
151
+ }
152
+ const finalPath = resolvedPath;
153
+ let contents;
154
+ try {
155
+ contents = fs$2.readFileSync(finalPath, "utf8");
156
+ } catch (error) {
157
+ if (error.code === "ENOENT") throw new Error(`File does not exist: ${finalPath}`);
158
+ throw new Error(`Failed to read file ${finalPath}: ${error}`);
159
+ }
160
+ if (finalPath.endsWith(".json")) try {
161
+ return JSON.parse(contents);
162
+ } catch (error) {
163
+ throw new Error(`Failed to parse JSON file ${finalPath}: ${error}`);
164
+ }
165
+ if (finalPath.endsWith(".yaml") || finalPath.endsWith(".yml")) try {
166
+ return yaml.load(contents);
167
+ } catch (error) {
168
+ throw new Error(`Failed to parse YAML file ${finalPath}: ${error}`);
169
+ }
170
+ if (finalPath.endsWith(".csv")) {
171
+ const records = parse$1(contents, { columns: true });
172
+ if (records.length > 0 && Object.keys(records[0]).length === 1) return records.map((record) => Object.values(record)[0]);
173
+ return records;
174
+ }
175
+ return contents;
176
+ }
177
+ /**
178
+ * Resolves a relative file path with respect to a base path, handling cloud configuration appropriately.
179
+ * When using a cloud configuration, the current working directory is always used instead of the context's base path.
180
+ *
181
+ * @param filePath - The relative or absolute file path to resolve.
182
+ * @param isCloudConfig - Whether this is a cloud configuration.
183
+ * @returns The resolved absolute file path.
184
+ */
185
+ function getResolvedRelativePath(filePath, isCloudConfig) {
186
+ if (path$1.isAbsolute(filePath) || !isCloudConfig) return filePath;
187
+ return path$1.join(process.cwd(), filePath);
188
+ }
189
+ /**
190
+ * Recursively loads external file references from a configuration object.
191
+ *
192
+ * @param config - The configuration object to process
193
+ * @param context - Optional context to control file loading behavior
194
+ * @returns The configuration with external file references resolved
195
+ */
196
+ function maybeLoadConfigFromExternalFile(config, context) {
197
+ if (Array.isArray(config)) return config.map((item) => maybeLoadConfigFromExternalFile(item, context));
198
+ if (typeof config === "object" && config !== null) {
199
+ const result = {};
200
+ for (const key of Object.keys(config)) {
201
+ const childContext = key === "value" && "type" in config && typeof config.type === "string" && (config.type === "python" || config.type === "javascript") ? "assertion" : key === "vars" ? "vars" : context;
202
+ const value = maybeLoadConfigFromExternalFile(config[key], childContext);
203
+ if (key === "__proto__") Object.defineProperty(result, key, {
204
+ value,
205
+ enumerable: true,
206
+ configurable: true,
207
+ writable: true
208
+ });
209
+ else result[key] = value;
210
+ }
211
+ return result;
212
+ }
213
+ return maybeLoadFromExternalFile(config, context);
214
+ }
215
+ /**
216
+ * Parses a file path or glob pattern to extract function names and file extensions.
217
+ * Function names can be specified in the filename like this:
218
+ * prompt.py:myFunction or prompts.js:myFunction.
219
+ * @param basePath - The base path for file resolution.
220
+ * @param promptPath - The path or glob pattern.
221
+ * @returns Parsed details including function name, file extension, and directory status.
222
+ */
223
+ function parsePathOrGlob(basePath, promptPath) {
224
+ if (promptPath.startsWith("file://")) promptPath = promptPath.slice(7);
225
+ const filePath = path$1.resolve(basePath, promptPath);
226
+ let filename = path$1.relative(basePath, filePath);
227
+ let functionName;
228
+ if (filename.includes(":")) {
229
+ const lastColonIndex = filename.lastIndexOf(":");
230
+ if (lastColonIndex > 1) {
231
+ const pathWithoutFunction = filename.slice(0, lastColonIndex);
232
+ if (isJavascriptFile(pathWithoutFunction) || pathWithoutFunction.endsWith(".py") || pathWithoutFunction.endsWith(".go") || pathWithoutFunction.endsWith(".rb")) {
233
+ functionName = filename.slice(lastColonIndex + 1);
234
+ filename = pathWithoutFunction;
235
+ }
236
+ }
237
+ }
238
+ let stats;
239
+ try {
240
+ stats = fs$2.statSync(path$1.join(basePath, filename));
241
+ } catch (err) {
242
+ if (getEnvBool("PROMPTFOO_STRICT_FILES")) throw err;
243
+ }
244
+ const normalizedFilePath = filePath.replace(/\\/g, "/");
245
+ const isPathPattern = stats?.isDirectory() || hasMagic(promptPath) || hasMagic(normalizedFilePath);
246
+ const safeFilename = path$1.relative(basePath, safeResolve(basePath, filename));
247
+ return {
248
+ extension: isPathPattern ? void 0 : path$1.parse(safeFilename).ext,
249
+ filePath: path$1.join(basePath, safeFilename),
250
+ functionName,
251
+ isPathPattern
252
+ };
253
+ }
254
+ function readOutput(outputPath) {
255
+ const ext = path$1.parse(outputPath).ext.slice(1);
256
+ switch (ext) {
257
+ case "json": return JSON.parse(fs$2.readFileSync(outputPath, "utf-8"));
258
+ default: throw new Error(`Unsupported output file format: ${ext} currently only supports json`);
259
+ }
260
+ }
261
+ /**
262
+ * Load custom Nunjucks filters from external files.
263
+ * Note: If a glob pattern matches multiple files, only the last file's export is used.
264
+ * Each filter name should typically resolve to a single file.
265
+ */
266
+ async function readFilters(filters, basePath = "") {
267
+ const ret = {};
268
+ for (const [name, filterPath] of Object.entries(filters)) {
269
+ const filePaths = globSync(path$1.join(basePath, filterPath), { windowsPathsNoEscape: true });
270
+ for (const filePath of filePaths) ret[name] = await importModule(path$1.resolve(filePath));
271
+ }
272
+ return ret;
273
+ }
274
+ /**
275
+ * Loads configuration from an external file with variable rendering.
276
+ * This is a convenience wrapper that combines renderVarsInObject and maybeLoadFromExternalFile.
277
+ *
278
+ * Use this for simple config fields that:
279
+ * - Need variable rendering ({{ vars.x }}, {{ env.X }})
280
+ * - May reference external files (file://path.json)
281
+ * - Don't have nested file references that need loading
282
+ *
283
+ * For fields with nested file references (like response_format.schema),
284
+ * use maybeLoadResponseFormatFromExternalFile instead.
285
+ *
286
+ * @param config - The configuration to process
287
+ * @param vars - Variables for template rendering
288
+ * @returns The processed configuration with variables rendered and files loaded
289
+ */
290
+ function maybeLoadFromExternalFileWithVars(config, vars) {
291
+ return maybeLoadFromExternalFile(renderVarsInObject(config, vars));
292
+ }
293
+ /**
294
+ * Loads response_format configuration from an external file with variable rendering.
295
+ *
296
+ * This function handles the special case where response_format may contain:
297
+ * 1. A top-level file reference (file://format.json)
298
+ * 2. A nested schema reference for json_schema type (schema: file://schema.json)
299
+ *
300
+ * Both levels need variable rendering and file loading.
301
+ *
302
+ * @param responseFormat - The response_format configuration
303
+ * @param vars - Variables for template rendering
304
+ * @returns The processed response_format with all files loaded
305
+ */
306
+ function maybeLoadResponseFormatFromExternalFile(responseFormat, vars) {
307
+ if (responseFormat === void 0 || responseFormat === null) return responseFormat;
308
+ const loaded = maybeLoadFromExternalFile(renderVarsInObject(responseFormat, vars));
309
+ if (!loaded || typeof loaded !== "object") return loaded;
310
+ if (loaded.type === "json_schema") {
311
+ const nestedSchema = loaded.schema || loaded.json_schema?.schema;
312
+ if (nestedSchema) {
313
+ const loadedSchema = maybeLoadFromExternalFile(renderVarsInObject(nestedSchema, vars));
314
+ if (loaded.schema !== void 0) return {
315
+ ...loaded,
316
+ schema: loadedSchema
317
+ };
318
+ else if (loaded.json_schema?.schema !== void 0) return {
319
+ ...loaded,
320
+ json_schema: {
321
+ ...loaded.json_schema,
322
+ schema: loadedSchema
323
+ }
324
+ };
325
+ }
326
+ }
327
+ return loaded;
328
+ }
329
+ /**
330
+ * Renders variables in a tools object and loads from external file if applicable.
331
+ * This function combines renderVarsInObject and maybeLoadFromExternalFile into a single step
332
+ * specifically for handling tools configurations.
333
+ *
334
+ * Supports loading from JSON, YAML, Python, and JavaScript files.
335
+ *
336
+ * @param tools - The tools configuration object or array to process.
337
+ * @param vars - Variables to use for rendering.
338
+ * @returns The processed tools configuration with variables rendered and content loaded from files if needed.
339
+ * @throws {Error} If the loaded tools are in an invalid format
340
+ */
341
+ async function maybeLoadToolsFromExternalFile(tools, vars) {
342
+ const rendered = renderVarsInObject(tools, vars);
343
+ if (typeof rendered === "string" && rendered.startsWith("file://")) {
344
+ const { filePath, functionName } = parseFileUrl(rendered);
345
+ if (functionName && (filePath.endsWith(".py") || isJavascriptFile(filePath))) {
346
+ const fileType = filePath.endsWith(".py") ? "Python" : "JavaScript";
347
+ logger.debug(`[maybeLoadToolsFromExternalFile] Loading tools from ${fileType} file: ${filePath}:${functionName}`);
348
+ try {
349
+ let toolDefinitions;
350
+ if (filePath.endsWith(".py")) {
351
+ const absPath = safeResolve(state.basePath || process.cwd(), filePath);
352
+ logger.debug(`[maybeLoadToolsFromExternalFile] Resolved Python path: ${absPath}`);
353
+ toolDefinitions = await runPython(absPath, functionName, []);
354
+ } else {
355
+ const absPath = safeResolve(state.basePath || process.cwd(), filePath);
356
+ logger.debug(`[maybeLoadToolsFromExternalFile] Resolved JavaScript path: ${absPath}`);
357
+ const module = await importModule(absPath);
358
+ const fn = module[functionName] || module.default?.[functionName];
359
+ if (typeof fn !== "function") {
360
+ const availableExports = Object.keys(module).filter((k) => k !== "default");
361
+ const basePath = state.basePath || process.cwd();
362
+ throw new Error(`Function "${functionName}" not found in ${filePath}. Available exports: ${availableExports.length > 0 ? availableExports.join(", ") : "(none)"}\nResolved from: ${basePath}`);
363
+ }
364
+ toolDefinitions = await Promise.resolve(fn());
365
+ }
366
+ if (!toolDefinitions || typeof toolDefinitions === "string" || typeof toolDefinitions === "number" || typeof toolDefinitions === "boolean") throw new Error(`Function "${functionName}" must return an array or object of tool definitions, but returned: ${toolDefinitions === null ? "null" : typeof toolDefinitions}`);
367
+ logger.debug(`[maybeLoadToolsFromExternalFile] Successfully loaded ${Array.isArray(toolDefinitions) ? toolDefinitions.length : "object"} tools`);
368
+ return toolDefinitions;
369
+ } catch (err) {
370
+ const errorMessage = err instanceof Error ? err.message : String(err);
371
+ const basePath = state.basePath || process.cwd();
372
+ throw new Error(`Failed to load tools from ${rendered}:\n${errorMessage}\n\nMake sure the function "${functionName}" exists and returns a valid tool definition array.\nResolved from: ${basePath}`);
373
+ }
374
+ }
375
+ if (filePath.endsWith(".py") || isJavascriptFile(filePath)) {
376
+ const ext = filePath.endsWith(".py") ? "Python" : "JavaScript";
377
+ const basePath = state.basePath || process.cwd();
378
+ throw new Error(`Cannot load tools from ${rendered}\n${ext} files require a function name. Use this format:\n tools: file://${filePath}:get_tools\n\nYour ${ext} file should export a function that returns tool definitions:\n` + (filePath.endsWith(".py") ? ` def get_tools():\n return [{"type": "function", "function": {...}}]` : ` module.exports.get_tools = () => [{ type: "function", function: {...} }];`) + `\n\nResolved from: ${basePath}`);
379
+ }
452
380
  }
453
- const finalPath = resolvedPath;
454
- let contents;
455
- try {
456
- contents = fs$2.readFileSync(finalPath, "utf8");
457
- } catch (error) {
458
- if (error.code === "ENOENT") throw new Error(`File does not exist: ${finalPath}`);
459
- throw new Error(`Failed to read file ${finalPath}: ${error}`);
381
+ if (Array.isArray(rendered)) {
382
+ const results = await Promise.all(rendered.map((item) => maybeLoadToolsFromExternalFile(item, vars)));
383
+ if (results.every((r) => Array.isArray(r))) return results.flat();
384
+ return results;
460
385
  }
461
- if (finalPath.endsWith(".json")) try {
462
- return JSON.parse(contents);
463
- } catch (error) {
464
- throw new Error(`Failed to parse JSON file ${finalPath}: ${error}`);
386
+ if (typeof rendered !== "string") return rendered;
387
+ const loaded = maybeLoadFromExternalFile(rendered);
388
+ if (loaded !== void 0 && loaded !== null && typeof loaded === "string") {
389
+ if (loaded.startsWith("file://")) throw new Error(`Failed to load tools from ${loaded}\nEnsure the file exists and contains valid JSON or YAML tool definitions.`);
390
+ if (loaded.includes("def ") || loaded.includes("import ")) throw new Error("Invalid tools configuration: file appears to contain Python code.\nPython files require a function name. Use this format:\n tools: file://tools.py:get_tools");
391
+ throw new Error("Invalid tools configuration: expected an array or object, but got a string.\nIf using file://, ensure the file contains valid JSON or YAML tool definitions.");
465
392
  }
466
- if (finalPath.endsWith(".yaml") || finalPath.endsWith(".yml")) try {
467
- return yaml.load(contents);
468
- } catch (error) {
469
- throw new Error(`Failed to parse YAML file ${finalPath}: ${error}`);
393
+ return loaded;
394
+ }
395
+ //#endregion
396
+ //#region src/util/providerRef.ts
397
+ const PROVIDER_OPTION_KEYS = new Set([
398
+ "id",
399
+ "label",
400
+ "config",
401
+ "prompts",
402
+ "transform",
403
+ "delay",
404
+ "env",
405
+ "inputs"
406
+ ]);
407
+ /** Returns true if the value is a non-empty string suitable as a provider identifier. */
408
+ function isValidProviderId(id) {
409
+ return typeof id === "string" && id !== "";
410
+ }
411
+ function getProviderLabel(provider) {
412
+ if ((typeof provider === "object" || typeof provider === "function") && provider !== null && "label" in provider && typeof provider.label === "string") return provider.label;
413
+ }
414
+ /**
415
+ * Resolves relative file paths in provider IDs to absolute paths for consistent matching.
416
+ * Handles file://, exec:, python:, golang: prefixes and bare .js/.ts/.mjs paths.
417
+ */
418
+ function canonicalizeProviderId(id) {
419
+ if (id.startsWith("file://")) {
420
+ const filePath = id.slice(7);
421
+ return path.isAbsolute(filePath) ? id : `file://${path.resolve(filePath)}`;
470
422
  }
471
- if (finalPath.endsWith(".csv")) {
472
- const records = parse$1(contents, { columns: true });
473
- if (records.length > 0 && Object.keys(records[0]).length === 1) return records.map((record) => Object.values(record)[0]);
474
- return records;
423
+ for (const prefix of [
424
+ "exec:",
425
+ "python:",
426
+ "golang:"
427
+ ]) if (id.startsWith(prefix)) {
428
+ const filePath = id.slice(prefix.length);
429
+ if (filePath.includes("/") || filePath.includes("\\")) return `${prefix}${path.resolve(filePath)}`;
430
+ return id;
475
431
  }
476
- return contents;
432
+ if ((id.endsWith(".js") || id.endsWith(".ts") || id.endsWith(".mjs")) && (id.includes("/") || id.includes("\\"))) return `file://${path.resolve(id)}`;
433
+ return id;
477
434
  }
478
435
  /**
479
- * Resolves a relative file path with respect to a base path, handling cloud configuration appropriately.
480
- * When using a cloud configuration, the current working directory is always used instead of the context's base path.
481
- *
482
- * @param filePath - The relative or absolute file path to resolve.
483
- * @param isCloudConfig - Whether this is a cloud configuration.
484
- * @returns The resolved absolute file path.
436
+ * Returns true for provider refs that should be expanded from YAML/JSON config files.
485
437
  */
486
- function getResolvedRelativePath(filePath, isCloudConfig) {
487
- if (path$1.isAbsolute(filePath) || !isCloudConfig) return filePath;
488
- return path$1.join(process.cwd(), filePath);
438
+ function isProviderConfigFileReference(providerPath) {
439
+ return providerPath.startsWith("file://") && (providerPath.endsWith(".yaml") || providerPath.endsWith(".yml") || providerPath.endsWith(".json"));
489
440
  }
490
441
  /**
491
- * Recursively loads external file references from a configuration object.
492
- *
493
- * @param config - The configuration object to process
494
- * @param context - Optional context to control file loading behavior
495
- * @returns The configuration with external file references resolved
442
+ * Reads a provider config file and normalizes single-provider and multi-provider files.
443
+ * Returns a `wasArray` flag so callers can detect multi-provider files that require
444
+ * `loadApiProviders` instead of `loadApiProvider`.
496
445
  */
497
- function maybeLoadConfigFromExternalFile(config, context) {
498
- if (Array.isArray(config)) return config.map((item) => maybeLoadConfigFromExternalFile(item, context));
499
- if (typeof config === "object" && config !== null) {
500
- const result = {};
501
- for (const key of Object.keys(config)) {
502
- const childContext = key === "value" && "type" in config && typeof config.type === "string" && (config.type === "python" || config.type === "javascript") ? "assertion" : key === "vars" ? "vars" : context;
503
- result[key] = maybeLoadConfigFromExternalFile(config[key], childContext);
504
- }
505
- return result;
446
+ function readProviderConfigFile(providerPath, basePath) {
447
+ const relativePath = providerPath.slice(7);
448
+ const resolvedPath = path.isAbsolute(relativePath) ? relativePath : path.join(basePath || process.cwd(), relativePath);
449
+ let rawContent;
450
+ try {
451
+ rawContent = yaml.load(fs.readFileSync(resolvedPath, "utf8"));
452
+ } catch (err) {
453
+ throw new Error(`Failed to load provider config ${relativePath}: ${err instanceof Error ? err.message : err}`);
506
454
  }
507
- return maybeLoadFromExternalFile(config, context);
455
+ const fileContent = maybeLoadConfigFromExternalFile(rawContent);
456
+ invariant(fileContent, `Provider config ${relativePath} is undefined`);
457
+ return {
458
+ configs: [fileContent].flat(),
459
+ relativePath,
460
+ wasArray: Array.isArray(fileContent)
461
+ };
508
462
  }
509
463
  /**
510
- * Parses a file path or glob pattern to extract function names and file extensions.
511
- * Function names can be specified in the filename like this:
512
- * prompt.py:myFunction or prompts.js:myFunction.
513
- * @param basePath - The base path for file resolution.
514
- * @param promptPath - The path or glob pattern.
515
- * @returns Parsed details including function name, file extension, and directory status.
464
+ * Loads provider config objects from a file-backed provider reference.
516
465
  */
517
- function parsePathOrGlob(basePath, promptPath) {
518
- if (promptPath.startsWith("file://")) promptPath = promptPath.slice(7);
519
- const filePath = path$1.resolve(basePath, promptPath);
520
- let filename = path$1.relative(basePath, filePath);
521
- let functionName;
522
- if (filename.includes(":")) {
523
- const lastColonIndex = filename.lastIndexOf(":");
524
- if (lastColonIndex > 1) {
525
- const pathWithoutFunction = filename.slice(0, lastColonIndex);
526
- if (isJavascriptFile(pathWithoutFunction) || pathWithoutFunction.endsWith(".py") || pathWithoutFunction.endsWith(".go") || pathWithoutFunction.endsWith(".rb")) {
527
- functionName = filename.slice(lastColonIndex + 1);
528
- filename = pathWithoutFunction;
466
+ function loadProviderConfigsFromFile(providerPath, basePath) {
467
+ return readProviderConfigFile(providerPath, basePath).configs;
468
+ }
469
+ /**
470
+ * Pure, synchronous classifier that converts every supported provider reference shape
471
+ * into a discriminated descriptor. Does not read files or instantiate providers.
472
+ */
473
+ function normalizeProviderRef(provider, options = {}) {
474
+ const { index } = options;
475
+ if (typeof provider === "string") {
476
+ if (!isValidProviderId(provider)) return {
477
+ kind: "unknown",
478
+ id: index === void 0 ? "unknown" : `unknown-${index}`
479
+ };
480
+ if (isProviderConfigFileReference(provider)) return {
481
+ kind: "file",
482
+ id: provider,
483
+ loadProviderPath: provider
484
+ };
485
+ return {
486
+ kind: "named",
487
+ id: provider,
488
+ loadProviderPath: provider
489
+ };
490
+ }
491
+ if (typeof provider === "function") {
492
+ const label = getProviderLabel(provider);
493
+ return {
494
+ kind: "function",
495
+ id: label ?? (index === void 0 ? "custom-function" : `custom-function-${index}`),
496
+ label
497
+ };
498
+ }
499
+ if (typeof provider === "object" && provider !== null && !Array.isArray(provider)) {
500
+ const providerId = provider.id;
501
+ const label = getProviderLabel(provider);
502
+ if (isValidProviderId(providerId)) return {
503
+ kind: "options",
504
+ id: providerId,
505
+ label,
506
+ loadOptions: provider,
507
+ loadProviderPath: providerId
508
+ };
509
+ const keys = Object.keys(provider);
510
+ if (keys.length === 1 && !PROVIDER_OPTION_KEYS.has(keys[0])) {
511
+ const originalId = keys[0];
512
+ const providerObject = provider[originalId];
513
+ if (typeof providerObject === "object" && providerObject !== null && !Array.isArray(providerObject) && isValidProviderId(originalId)) {
514
+ const id = isValidProviderId(providerObject.id) ? providerObject.id : originalId;
515
+ return {
516
+ kind: "map",
517
+ id,
518
+ label: getProviderLabel(providerObject),
519
+ loadOptions: {
520
+ ...providerObject,
521
+ id
522
+ },
523
+ loadProviderPath: originalId
524
+ };
529
525
  }
530
526
  }
527
+ if (isValidProviderId(label)) return {
528
+ kind: "unknown",
529
+ id: label,
530
+ label
531
+ };
531
532
  }
532
- let stats;
533
- try {
534
- stats = fs$2.statSync(path$1.join(basePath, filename));
535
- } catch (err) {
536
- if (getEnvBool("PROMPTFOO_STRICT_FILES")) throw err;
537
- }
538
- const normalizedFilePath = filePath.replace(/\\/g, "/");
539
- const isPathPattern = stats?.isDirectory() || hasMagic(promptPath) || hasMagic(normalizedFilePath);
540
- const safeFilename = path$1.relative(basePath, safeResolve(basePath, filename));
541
533
  return {
542
- extension: isPathPattern ? void 0 : path$1.parse(safeFilename).ext,
543
- filePath: path$1.join(basePath, safeFilename),
544
- functionName,
545
- isPathPattern
534
+ kind: "unknown",
535
+ id: index === void 0 ? "unknown" : `unknown-${index}`
546
536
  };
547
537
  }
548
- function readOutput(outputPath) {
549
- const ext = path$1.parse(outputPath).ext.slice(1);
550
- switch (ext) {
551
- case "json": return JSON.parse(fs$2.readFileSync(outputPath, "utf-8"));
552
- default: throw new Error(`Unsupported output file format: ${ext} currently only supports json`);
538
+ //#endregion
539
+ //#region src/util/provider.ts
540
+ function providerToIdentifier(provider) {
541
+ if (!provider) return;
542
+ if (typeof provider === "string") return canonicalizeProviderId(provider);
543
+ const { label } = normalizeProviderRef(provider);
544
+ if (label) return label;
545
+ if (isApiProvider(provider)) return canonicalizeProviderId(provider.id());
546
+ if (isProviderOptions(provider)) {
547
+ if (provider.id) return canonicalizeProviderId(provider.id);
548
+ return;
549
+ }
550
+ if (typeof provider === "object" && "id" in provider && typeof provider.id === "string") return canonicalizeProviderId(provider.id);
551
+ }
552
+ /**
553
+ * Gets a descriptive identifier string for a provider, showing both label and ID when both exist.
554
+ * Useful for error messages to help users debug provider reference issues.
555
+ */
556
+ function getProviderDescription(provider) {
557
+ const label = provider.label;
558
+ const id = provider.id();
559
+ if (label && label !== id) return `${label} (${id})`;
560
+ return id;
561
+ }
562
+ /**
563
+ * Checks if a provider reference matches a given provider.
564
+ * Supports exact matching and wildcard patterns.
565
+ */
566
+ function doesProviderRefMatch(ref, provider) {
567
+ const label = provider.label;
568
+ const id = provider.id();
569
+ const canonicalRef = canonicalizeProviderId(ref);
570
+ const canonicalId = canonicalizeProviderId(id);
571
+ if (label && label === ref) return true;
572
+ if (id === ref || canonicalId === canonicalRef) return true;
573
+ if (ref.endsWith("*")) {
574
+ const prefix = ref.slice(0, -1);
575
+ if (label?.startsWith(prefix) || id.startsWith(prefix) || canonicalId.startsWith(prefix)) return true;
576
+ }
577
+ if (label?.startsWith(`${ref}:`) || id.startsWith(`${ref}:`) || canonicalId.startsWith(`${ref}:`)) return true;
578
+ return false;
579
+ }
580
+ /**
581
+ * Checks if a provider is allowed based on a list of allowed references.
582
+ */
583
+ function isProviderAllowed(provider, allowedProviders) {
584
+ if (!Array.isArray(allowedProviders)) return true;
585
+ if (allowedProviders.length === 0) return false;
586
+ return allowedProviders.some((ref) => doesProviderRefMatch(ref, provider));
587
+ }
588
+ /**
589
+ * Detects if a provider uses OpenAI models.
590
+ * This includes direct OpenAI providers and Azure OpenAI.
591
+ */
592
+ function isOpenAiProvider(providerId) {
593
+ const lowerProviderId = providerId.toLowerCase();
594
+ if (lowerProviderId.startsWith("openai:")) return true;
595
+ if (lowerProviderId.startsWith("azureopenai:")) return true;
596
+ if (lowerProviderId.startsWith("azure:")) {
597
+ if ([
598
+ "gpt",
599
+ "openai",
600
+ "davinci",
601
+ "curie",
602
+ "babbage",
603
+ "ada",
604
+ "text-embedding",
605
+ "whisper",
606
+ "dall-e",
607
+ "tts"
608
+ ].some((indicator) => lowerProviderId.includes(indicator))) return true;
609
+ }
610
+ return false;
611
+ }
612
+ /**
613
+ * Detects if a provider uses Anthropic/Claude models.
614
+ * This includes direct Anthropic providers, Bedrock with Claude, and Vertex with Claude.
615
+ */
616
+ function isAnthropicProvider(providerId) {
617
+ const lowerProviderId = providerId.toLowerCase();
618
+ if (lowerProviderId.startsWith("anthropic:")) return true;
619
+ if (lowerProviderId.startsWith("bedrock:")) {
620
+ if (lowerProviderId.includes("claude") || lowerProviderId.includes("anthropic")) return true;
621
+ }
622
+ if (lowerProviderId.startsWith("vertex:")) {
623
+ if (lowerProviderId.includes("claude")) return true;
624
+ }
625
+ return false;
626
+ }
627
+ const KNOWN_ENV_VARS = {
628
+ openai: "OPENAI_API_KEY",
629
+ anthropic: "ANTHROPIC_API_KEY",
630
+ google: "GOOGLE_API_KEY",
631
+ mistral: "MISTRAL_API_KEY",
632
+ cohere: "COHERE_API_KEY",
633
+ replicate: "REPLICATE_API_TOKEN",
634
+ voyage: "VOYAGE_API_KEY",
635
+ ai21: "AI21_API_KEY",
636
+ xai: "XAI_API_KEY",
637
+ groq: "GROQ_API_KEY",
638
+ deepseek: "DEEPSEEK_API_KEY",
639
+ perplexity: "PERPLEXITY_API_KEY",
640
+ hyperbolic: "HYPERBOLIC_API_KEY",
641
+ cerebras: "CEREBRAS_API_KEY",
642
+ togetherai: "TOGETHER_API_KEY",
643
+ fal: "FAL_KEY",
644
+ huggingface: "HF_TOKEN",
645
+ "cloudflare-ai": "CLOUDFLARE_API_KEY"
646
+ };
647
+ function getDefaultEnvVar(providerId) {
648
+ const prefix = providerId.split(":")[0];
649
+ return KNOWN_ENV_VARS[prefix] || `${prefix.toUpperCase()}_API_KEY`;
650
+ }
651
+ /**
652
+ * Pre-checks providers for missing API keys before evaluation starts.
653
+ * Assumes getApiKey() is side-effect free (no network calls or token refresh).
654
+ */
655
+ function checkProviderApiKeys(providers) {
656
+ const missingApiKeys = /* @__PURE__ */ new Map();
657
+ for (const provider of providers) {
658
+ const p = provider;
659
+ if (typeof p.getApiKey !== "function") continue;
660
+ if (provider.id().startsWith("azure:")) continue;
661
+ const requiresKey = typeof p.requiresApiKey === "function" ? p.requiresApiKey() : p.config?.apiKeyRequired !== false;
662
+ let apiKey;
663
+ try {
664
+ apiKey = p.getApiKey();
665
+ } catch {
666
+ apiKey = void 0;
667
+ }
668
+ if (requiresKey && !apiKey) {
669
+ const envVar = p.config?.apiKeyEnvar || getDefaultEnvVar(provider.id());
670
+ if (!missingApiKeys.has(envVar)) missingApiKeys.set(envVar, []);
671
+ missingApiKeys.get(envVar).push(provider.id());
672
+ }
553
673
  }
674
+ return missingApiKeys;
554
675
  }
555
676
  /**
556
- * Load custom Nunjucks filters from external files.
557
- * Note: If a glob pattern matches multiple files, only the last file's export is used.
558
- * Each filter name should typically resolve to a single file.
677
+ * Detects if a provider uses Google models.
678
+ * This includes direct Google/Vertex providers with Gemini and other Google models.
679
+ * Note: Vertex with Claude models is NOT counted as Google (it's Anthropic).
559
680
  */
560
- async function readFilters(filters, basePath = "") {
561
- const ret = {};
562
- for (const [name, filterPath] of Object.entries(filters)) {
563
- const filePaths = globSync(path$1.join(basePath, filterPath), { windowsPathsNoEscape: true });
564
- for (const filePath of filePaths) ret[name] = await importModule(path$1.resolve(filePath));
681
+ function isGoogleProvider(providerId) {
682
+ const lowerProviderId = providerId.toLowerCase();
683
+ if (lowerProviderId.startsWith("google:")) return true;
684
+ if (lowerProviderId.startsWith("vertex:")) {
685
+ if (!lowerProviderId.includes("claude")) return true;
565
686
  }
566
- return ret;
687
+ return false;
567
688
  }
689
+ //#endregion
690
+ //#region src/util/comparison.ts
568
691
  /**
569
- * Loads configuration from an external file with variable rendering.
570
- * This is a convenience wrapper that combines renderVarsInObject and maybeLoadFromExternalFile.
692
+ * Explicit runtime variable names that don't follow the underscore convention.
693
+ * These are added during evaluation but aren't part of the original test definition.
571
694
  *
572
- * Use this for simple config fields that:
573
- * - Need variable rendering ({{ vars.x }}, {{ env.X }})
574
- * - May reference external files (file://path.json)
575
- * - Don't have nested file references that need loading
695
+ * - sessionId: Added by multi-turn strategy providers (GOAT, Crescendo)
576
696
  *
577
- * For fields with nested file references (like response_format.schema),
578
- * use maybeLoadResponseFormatFromExternalFile instead.
697
+ * Note: Variables starting with underscore (e.g., _conversation) are automatically
698
+ * treated as runtime variables and filtered out.
699
+ */
700
+ const EXPLICIT_RUNTIME_VAR_KEYS = ["sessionId"];
701
+ /**
702
+ * Checks if a variable key is a runtime-only variable that should be filtered
703
+ * when comparing test cases.
579
704
  *
580
- * @param config - The configuration to process
581
- * @param vars - Variables for template rendering
582
- * @returns The processed configuration with variables rendered and files loaded
705
+ * Runtime variables are identified by:
706
+ * 1. Starting with underscore (_) - convention for internal/runtime vars
707
+ * 2. Being in the explicit runtime var list (for legacy vars like sessionId)
583
708
  */
584
- function maybeLoadFromExternalFileWithVars(config, vars) {
585
- return maybeLoadFromExternalFile(renderVarsInObject(config, vars));
709
+ function isRuntimeVar(key) {
710
+ return key.startsWith("_") || EXPLICIT_RUNTIME_VAR_KEYS.includes(key);
586
711
  }
587
712
  /**
588
- * Loads response_format configuration from an external file with variable rendering.
713
+ * Filters out runtime-only variables that are added during evaluation
714
+ * but aren't part of the original test definition.
589
715
  *
590
- * This function handles the special case where response_format may contain:
591
- * 1. A top-level file reference (file://format.json)
592
- * 2. A nested schema reference for json_schema type (schema: file://schema.json)
716
+ * This is used when comparing test cases to determine if a result
717
+ * corresponds to a particular test, regardless of runtime state.
593
718
  *
594
- * Both levels need variable rendering and file loading.
719
+ * Runtime variables are identified by:
720
+ * - Starting with underscore (e.g., _conversation, _metadata)
721
+ * - Being in the explicit list (e.g., sessionId for backward compatibility)
722
+ */
723
+ function filterRuntimeVars(vars) {
724
+ if (!vars || typeof vars !== "object" || Array.isArray(vars)) return vars;
725
+ const filtered = {};
726
+ for (const [key, value] of Object.entries(vars)) if (!isRuntimeVar(key)) filtered[key] = value;
727
+ return filtered;
728
+ }
729
+ /**
730
+ * Extracts only runtime variables from a vars object.
731
+ * This is the inverse of filterRuntimeVars.
595
732
  *
596
- * @param responseFormat - The response_format configuration
597
- * @param vars - Variables for template rendering
598
- * @returns The processed response_format with all files loaded
733
+ * Used to restore runtime state when re-running filtered tests.
599
734
  */
600
- function maybeLoadResponseFormatFromExternalFile(responseFormat, vars) {
601
- if (responseFormat === void 0 || responseFormat === null) return responseFormat;
602
- const loaded = maybeLoadFromExternalFile(renderVarsInObject(responseFormat, vars));
603
- if (!loaded || typeof loaded !== "object") return loaded;
604
- if (loaded.type === "json_schema") {
605
- const nestedSchema = loaded.schema || loaded.json_schema?.schema;
606
- if (nestedSchema) {
607
- const loadedSchema = maybeLoadFromExternalFile(renderVarsInObject(nestedSchema, vars));
608
- if (loaded.schema !== void 0) return {
609
- ...loaded,
610
- schema: loadedSchema
611
- };
612
- else if (loaded.json_schema?.schema !== void 0) return {
613
- ...loaded,
614
- json_schema: {
615
- ...loaded.json_schema,
616
- schema: loadedSchema
617
- }
618
- };
619
- }
620
- }
621
- return loaded;
735
+ function extractRuntimeVars(vars) {
736
+ if (!vars || typeof vars !== "object" || Array.isArray(vars)) return;
737
+ const extracted = {};
738
+ for (const [key, value] of Object.entries(vars)) if (isRuntimeVar(key)) extracted[key] = value;
739
+ return Object.keys(extracted).length > 0 ? extracted : void 0;
740
+ }
741
+ function varsMatch(vars1, vars2) {
742
+ return deepEqual(vars1, vars2);
622
743
  }
623
744
  /**
624
- * Renders variables in a tools object and loads from external file if applicable.
625
- * This function combines renderVarsInObject and maybeLoadFromExternalFile into a single step
626
- * specifically for handling tools configurations.
745
+ * Generate a unique key for a test case for deduplication purposes.
746
+ * Excludes runtime variables and includes strategyId to distinguish tests
747
+ * with the same prompt but different strategies.
627
748
  *
628
- * Supports loading from JSON, YAML, Python, and JavaScript files.
749
+ * @param testCase - The test case to generate a key for
750
+ * @returns A JSON string that uniquely identifies the test case
751
+ */
752
+ function getTestCaseDeduplicationKey(testCase) {
753
+ const filteredVars = filterRuntimeVars(testCase.vars);
754
+ const strategyId = testCase.metadata?.strategyId || "none";
755
+ return JSON.stringify({
756
+ vars: filteredVars,
757
+ strategyId
758
+ });
759
+ }
760
+ /**
761
+ * Deduplicates an array of test cases based on their vars and strategyId.
762
+ * Tests with the same vars but different strategies are considered different.
763
+ * Runtime variables (like _conversation, sessionId) are filtered out before comparison.
629
764
  *
630
- * @param tools - The tools configuration object or array to process.
631
- * @param vars - Variables to use for rendering.
632
- * @returns The processed tools configuration with variables rendered and content loaded from files if needed.
633
- * @throws {Error} If the loaded tools are in an invalid format
765
+ * @param tests - Array of test cases to deduplicate
766
+ * @returns Deduplicated array of test cases
634
767
  */
635
- async function maybeLoadToolsFromExternalFile(tools, vars) {
636
- const rendered = renderVarsInObject(tools, vars);
637
- if (typeof rendered === "string" && rendered.startsWith("file://")) {
638
- const { filePath, functionName } = parseFileUrl(rendered);
639
- if (functionName && (filePath.endsWith(".py") || isJavascriptFile(filePath))) {
640
- const fileType = filePath.endsWith(".py") ? "Python" : "JavaScript";
641
- logger.debug(`[maybeLoadToolsFromExternalFile] Loading tools from ${fileType} file: ${filePath}:${functionName}`);
642
- try {
643
- let toolDefinitions;
644
- if (filePath.endsWith(".py")) {
645
- const absPath = safeResolve(state.basePath || process.cwd(), filePath);
646
- logger.debug(`[maybeLoadToolsFromExternalFile] Resolved Python path: ${absPath}`);
647
- toolDefinitions = await runPython(absPath, functionName, []);
648
- } else {
649
- const absPath = safeResolve(state.basePath || process.cwd(), filePath);
650
- logger.debug(`[maybeLoadToolsFromExternalFile] Resolved JavaScript path: ${absPath}`);
651
- const module = await importModule(absPath);
652
- const fn = module[functionName] || module.default?.[functionName];
653
- if (typeof fn !== "function") {
654
- const availableExports = Object.keys(module).filter((k) => k !== "default");
655
- const basePath = state.basePath || process.cwd();
656
- throw new Error(`Function "${functionName}" not found in ${filePath}. Available exports: ${availableExports.length > 0 ? availableExports.join(", ") : "(none)"}\nResolved from: ${basePath}`);
657
- }
658
- toolDefinitions = await Promise.resolve(fn());
659
- }
660
- if (!toolDefinitions || typeof toolDefinitions === "string" || typeof toolDefinitions === "number" || typeof toolDefinitions === "boolean") throw new Error(`Function "${functionName}" must return an array or object of tool definitions, but returned: ${toolDefinitions === null ? "null" : typeof toolDefinitions}`);
661
- logger.debug(`[maybeLoadToolsFromExternalFile] Successfully loaded ${Array.isArray(toolDefinitions) ? toolDefinitions.length : "object"} tools`);
662
- return toolDefinitions;
663
- } catch (err) {
664
- const errorMessage = err instanceof Error ? err.message : String(err);
665
- const basePath = state.basePath || process.cwd();
666
- throw new Error(`Failed to load tools from ${rendered}:\n${errorMessage}\n\nMake sure the function "${functionName}" exists and returns a valid tool definition array.\nResolved from: ${basePath}`);
667
- }
668
- }
669
- if (filePath.endsWith(".py") || isJavascriptFile(filePath)) {
670
- const ext = filePath.endsWith(".py") ? "Python" : "JavaScript";
671
- const basePath = state.basePath || process.cwd();
672
- throw new Error(`Cannot load tools from ${rendered}\n${ext} files require a function name. Use this format:\n tools: file://${filePath}:get_tools\n\nYour ${ext} file should export a function that returns tool definitions:\n` + (filePath.endsWith(".py") ? ` def get_tools():\n return [{"type": "function", "function": {...}}]` : ` module.exports.get_tools = () => [{ type: "function", function: {...} }];`) + `\n\nResolved from: ${basePath}`);
673
- }
674
- }
675
- if (Array.isArray(rendered)) {
676
- const results = await Promise.all(rendered.map((item) => maybeLoadToolsFromExternalFile(item, vars)));
677
- if (results.every((r) => Array.isArray(r))) return results.flat();
678
- return results;
679
- }
680
- if (typeof rendered !== "string") return rendered;
681
- const loaded = maybeLoadFromExternalFile(rendered);
682
- if (loaded !== void 0 && loaded !== null && typeof loaded === "string") {
683
- if (loaded.startsWith("file://")) throw new Error(`Failed to load tools from ${loaded}\nEnsure the file exists and contains valid JSON or YAML tool definitions.`);
684
- if (loaded.includes("def ") || loaded.includes("import ")) throw new Error("Invalid tools configuration: file appears to contain Python code.\nPython files require a function name. Use this format:\n tools: file://tools.py:get_tools");
685
- throw new Error("Invalid tools configuration: expected an array or object, but got a string.\nIf using file://, ensure the file contains valid JSON or YAML tool definitions.");
768
+ function deduplicateTestCases(tests) {
769
+ const seen = /* @__PURE__ */ new Set();
770
+ return tests.filter((test) => {
771
+ const key = getTestCaseDeduplicationKey(test);
772
+ if (seen.has(key)) return false;
773
+ seen.add(key);
774
+ return true;
775
+ });
776
+ }
777
+ function resultIsForTestCase(result, testCase) {
778
+ const testProviderId = testCase.provider ? providerToIdentifier(testCase.provider) : void 0;
779
+ const resultProviderId = providerToIdentifier(result.provider);
780
+ const providersMatch = !testProviderId || !resultProviderId || testProviderId === resultProviderId;
781
+ const resultVars = filterRuntimeVars(result.vars);
782
+ const testVars = filterRuntimeVars(testCase.vars);
783
+ const doVarsMatch = varsMatch(testVars, resultVars);
784
+ const isMatch = doVarsMatch && providersMatch;
785
+ if (!isMatch) {
786
+ const varKeys = testVars ? Object.keys(testVars).join(", ") : "none";
787
+ logger.debug(`[resultIsForTestCase] No match: vars=${doVarsMatch}, providers=${providersMatch}`, {
788
+ testProvider: testProviderId || "none",
789
+ resultProvider: resultProviderId || "none",
790
+ testVarKeys: varKeys
791
+ });
686
792
  }
687
- return loaded;
793
+ return isMatch;
794
+ }
795
+ //#endregion
796
+ //#region src/util/env.ts
797
+ /**
798
+ * Load environment variables from .env file(s).
799
+ * @param envPath - Single path, array of paths, or undefined for default .env loading.
800
+ * When paths are explicitly specified, all files must exist or an error is thrown.
801
+ * When multiple files are provided, later files override values from earlier files.
802
+ */
803
+ function setupEnv(envPath) {
804
+ if (envPath) {
805
+ const paths = (Array.isArray(envPath) ? envPath : [envPath]).flatMap((p) => p.includes(",") ? p.split(",").map((s) => s.trim()) : p.trim()).filter((p) => p.length > 0);
806
+ if (paths.length === 0) {
807
+ dotenv.config({ quiet: true });
808
+ return;
809
+ }
810
+ for (const p of paths) if (!fs$2.existsSync(p)) throw new Error(`Environment file not found: ${p}`);
811
+ if (paths.length === 1) logger.info(`Loading environment variables from ${paths[0]}`);
812
+ else logger.info(`Loading environment variables from: ${paths.join(", ")}`);
813
+ const pathArg = paths.length === 1 ? paths[0] : paths;
814
+ dotenv.config({
815
+ path: pathArg,
816
+ override: true,
817
+ quiet: true
818
+ });
819
+ } else dotenv.config({ quiet: true });
688
820
  }
689
821
  //#endregion
690
822
  //#region src/googleSheets.ts
@@ -965,6 +1097,34 @@ function evalTableToCsv(table, options = { isRedteam: false }) {
965
1097
  function evalTableToJson(table) {
966
1098
  return table;
967
1099
  }
1100
+ function getEvalTableOutputPromptLocationsBySize(payload) {
1101
+ return payload.table.body.flatMap((row, rowIndex) => row.outputs.flatMap((output, outputIndex) => output?.prompt ? [{
1102
+ rowIndex,
1103
+ outputIndex,
1104
+ length: output.prompt.length
1105
+ }] : [])).sort((a, b) => b.length - a.length);
1106
+ }
1107
+ function stripEvalTableOutputPrompts(payload, locationsToStrip) {
1108
+ return {
1109
+ ...payload,
1110
+ table: {
1111
+ ...payload.table,
1112
+ body: payload.table.body.map((row, rowIndex) => ({
1113
+ ...row,
1114
+ outputs: row.outputs.map((output, outputIndex) => {
1115
+ if (!output || !locationsToStrip.has(`${rowIndex}:${outputIndex}`)) return output;
1116
+ return {
1117
+ ...output,
1118
+ prompt: ""
1119
+ };
1120
+ })
1121
+ }))
1122
+ }
1123
+ };
1124
+ }
1125
+ function getEvalTablePromptStrippedPayload(payload, promptLocations, promptCountToStrip) {
1126
+ return stripEvalTableOutputPrompts(payload, new Set(promptLocations.slice(0, promptCountToStrip).map(({ rowIndex, outputIndex }) => `${rowIndex}:${outputIndex}`)));
1127
+ }
968
1128
  /**
969
1129
  * Merges comparison tables with the main table for side-by-side CSV export.
970
1130
  *
@@ -1164,7 +1324,7 @@ function createOutputMetadata(evalRecord) {
1164
1324
  arch: os$1.arch(),
1165
1325
  exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
1166
1326
  evaluationCreatedAt,
1167
- author: evalRecord.author
1327
+ author: evalRecord.author ?? void 0
1168
1328
  };
1169
1329
  }
1170
1330
  /**
@@ -1299,6 +1459,6 @@ function printBorder() {
1299
1459
  logger.info(border);
1300
1460
  }
1301
1461
  //#endregion
1302
- export { getProviderDescription as A, deduplicateTestCases as C, resultIsForTestCase as D, getTestCaseDeduplicationKey as E, isGoogleProvider as M, isOpenAiProvider as N, checkProviderApiKeys as O, isProviderAllowed as P, setupEnv as S, filterRuntimeVars as T, parsePathOrGlob as _, ComparisonEvalNotFoundError as a, loadFunction as b, mergeComparisonTables as c, getResolvedRelativePath as d, maybeLoadConfigFromExternalFile as f, maybeLoadToolsFromExternalFile as g, maybeLoadResponseFormatFromExternalFile as h, writeOutput as i, isAnthropicProvider as j, doesProviderRefMatch as k, fetchCsvFromGoogleSheet as l, maybeLoadFromExternalFileWithVars as m, createOutputMetadata as n, evalTableToJson as o, maybeLoadFromExternalFile as p, writeMultipleOutputs as r, generateEvalCsv as s, printBorder as t, getNunjucksEngineForFilePath as u, readFilters as v, extractRuntimeVars as w, parseFileUrl as x, readOutput as y };
1462
+ export { getResolvedRelativePath as A, parseFileUrl as B, isOpenAiProvider as C, normalizeProviderRef as D, loadProviderConfigsFromFile as E, maybeLoadToolsFromExternalFile as F, parsePathOrGlob as I, readFilters as L, maybeLoadFromExternalFile as M, maybeLoadFromExternalFileWithVars as N, readProviderConfigFile as O, maybeLoadResponseFormatFromExternalFile as P, readOutput as R, isGoogleProvider as S, isProviderConfigFileReference as T, resultIsForTestCase as _, ComparisonEvalNotFoundError as a, getProviderDescription as b, getEvalTableOutputPromptLocationsBySize as c, fetchCsvFromGoogleSheet as d, setupEnv as f, getTestCaseDeduplicationKey as g, filterRuntimeVars as h, writeOutput as i, maybeLoadConfigFromExternalFile as j, getNunjucksEngineForFilePath as k, getEvalTablePromptStrippedPayload as l, extractRuntimeVars as m, createOutputMetadata as n, evalTableToJson as o, deduplicateTestCases as p, writeMultipleOutputs as r, generateEvalCsv as s, printBorder as t, mergeComparisonTables as u, checkProviderApiKeys as v, isProviderAllowed as w, isAnthropicProvider as x, doesProviderRefMatch as y, loadFunction as z };
1303
1463
 
1304
- //# sourceMappingURL=util-DxWpWjhc.js.map
1464
+ //# sourceMappingURL=util-DURocbYR.js.map