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
@@ -0,0 +1,1334 @@
1
+ import { C as getEnvFloat, S as getEnvBool, a as logger, k as state, p as sanitizeUrl, w as getEnvInt, y as safeJsonStringify } from "./logger-KD8JjCRJ.js";
2
+ import { g as parseRetryAfter, h as parseRateLimitHeaders, m as sleep, o as withFetchRetryContext } from "./fetch-BufrQtvR.js";
3
+ import { t as invariant } from "./invariant-DIYf9sP1.js";
4
+ import { m as isProviderOptions, p as isApiProvider } from "./types-BJQBBPTP.js";
5
+ import { u as isTransientConnectionError } from "./cache-roFAE0cI.js";
6
+ import { a as createEmptyTokenUsage, r as accumulateTokenUsage } from "./tokenUsageUtils-BjVkdk18.js";
7
+ import { n as isBlobStorageEnabled, r as shouldAttemptRemoteBlobUpload, t as extractAndStoreBinaryData } from "./extractor-BR7XAzAL.js";
8
+ import { t as OpenAiChatCompletionProvider } from "./chat-CUCorGiL.js";
9
+ import { t as PromptfooChatCompletionProvider } from "./promptfoo-BDrfT30-.js";
10
+ import { o as transform, r as TransformInputType } from "./transform-CrPGTsij.js";
11
+ import { i as throwIfTargetPromptExceedsMaxChars } from "./promptLength-0qIHyhA5.js";
12
+ import { createHash, randomUUID } from "crypto";
13
+ import { EventEmitter } from "events";
14
+ //#region src/scheduler/types.ts
15
+ /**
16
+ * Default rate limit detection for ProviderResponse.
17
+ * Checks HTTP status, error fields, and error messages.
18
+ */
19
+ function isProviderResponseRateLimited(result, error) {
20
+ return Boolean(result?.metadata?.http?.status === 429 || result?.error?.includes?.("429") || result?.error?.toLowerCase?.().includes?.("rate limit") || error?.message?.includes("429") || error?.message?.toLowerCase().includes("rate limit") || error?.message?.toLowerCase().includes("too many requests"));
21
+ }
22
+ /**
23
+ * Extract rate limit headers from ProviderResponse.
24
+ * Headers can be at metadata.http.headers or metadata.headers.
25
+ */
26
+ function getProviderResponseHeaders(result) {
27
+ return result?.metadata?.http?.headers || result?.metadata?.headers;
28
+ }
29
+ //#endregion
30
+ //#region src/scheduler/providerWrapper.ts
31
+ /**
32
+ * Provider wrapper that adds rate limiting to any ApiProvider.
33
+ *
34
+ * Use this to wrap providers before passing them to redteam/assertion
35
+ * code paths that bypass the main evaluator.
36
+ */
37
+ /**
38
+ * Symbol to mark providers that have already been wrapped.
39
+ * Prevents double-wrapping which could cause issues.
40
+ */
41
+ const WRAPPED_SYMBOL = Symbol.for("promptfoo.rateLimitWrapped");
42
+ /**
43
+ * Check if a provider is already wrapped with rate limiting.
44
+ */
45
+ function isRateLimitWrapped(provider) {
46
+ return provider[WRAPPED_SYMBOL] === true;
47
+ }
48
+ /**
49
+ * Create rate limit detection options for ProviderResponse.
50
+ * Shared between providerWrapper and evaluator for consistency.
51
+ */
52
+ function createProviderRateLimitOptions() {
53
+ return {
54
+ getHeaders: getProviderResponseHeaders,
55
+ isRateLimited: isProviderResponseRateLimited,
56
+ getRetryAfter: (result, error) => {
57
+ const rawHeaders = getProviderResponseHeaders(result);
58
+ if (rawHeaders) {
59
+ const headers = {};
60
+ for (const [key, value] of Object.entries(rawHeaders)) headers[key.toLowerCase()] = value;
61
+ if (headers["retry-after-ms"]) {
62
+ const ms = parseInt(headers["retry-after-ms"], 10);
63
+ if (!isNaN(ms) && ms >= 0) return ms;
64
+ }
65
+ if (headers["retry-after"]) {
66
+ const parsed = parseRetryAfter(headers["retry-after"]);
67
+ if (parsed !== null) return parsed;
68
+ }
69
+ }
70
+ const match = error?.message?.match(/\bretry after (\d+)\b/i);
71
+ if (match) return parseInt(match[1], 10) * 1e3;
72
+ }
73
+ };
74
+ }
75
+ /**
76
+ * Wrap a provider with rate limiting.
77
+ *
78
+ * The wrapped provider will use the registry for all callApi calls,
79
+ * automatically handling rate limits, retries, and adaptive concurrency.
80
+ *
81
+ * @param provider - The provider to wrap
82
+ * @param registry - The rate limit registry to use
83
+ * @returns A wrapped provider that applies rate limiting
84
+ */
85
+ function wrapProviderWithRateLimiting(provider, registry) {
86
+ if (isRateLimitWrapped(provider)) return provider;
87
+ const originalCallApi = provider.callApi.bind(provider);
88
+ const wrappedProvider = {
89
+ ...provider,
90
+ id: () => provider.id(),
91
+ callApi: async (prompt, context, options) => {
92
+ return registry.execute(provider, () => originalCallApi(prompt, context, options), createProviderRateLimitOptions());
93
+ }
94
+ };
95
+ wrappedProvider[WRAPPED_SYMBOL] = true;
96
+ return wrappedProvider;
97
+ }
98
+ //#endregion
99
+ //#region src/scheduler/adaptiveConcurrency.ts
100
+ const DEFAULT_MIN_CONCURRENCY = 1;
101
+ const BACKOFF_FACTOR = .5;
102
+ const RECOVERY_FACTOR = 1.5;
103
+ const RECOVERY_THRESHOLD = 5;
104
+ const WARNING_THRESHOLD = .1;
105
+ /**
106
+ * Manages adaptive concurrency based on rate limit feedback.
107
+ *
108
+ * Recovery path with constants (initial=10, min=1):
109
+ * 1 → ceil(1.5) = 2 (5 successes)
110
+ * 2 → ceil(3.0) = 3 (5 successes)
111
+ * 3 → ceil(4.5) = 5 (5 successes)
112
+ * 5 → ceil(7.5) = 8 (5 successes)
113
+ * 8 → ceil(12) = 10 (5 successes, capped at initial)
114
+ *
115
+ * Total: 25 requests to fully recover from min=1 to initial=10
116
+ */
117
+ var AdaptiveConcurrency = class {
118
+ current;
119
+ initial;
120
+ min;
121
+ consecutiveSuccesses = 0;
122
+ constructor(initial, min = DEFAULT_MIN_CONCURRENCY) {
123
+ this.initial = initial;
124
+ this.current = initial;
125
+ this.min = Math.min(initial, Math.max(1, min));
126
+ }
127
+ /**
128
+ * Called on successful request.
129
+ * May increase concurrency after sustained success.
130
+ */
131
+ recordSuccess() {
132
+ this.consecutiveSuccesses++;
133
+ if (this.consecutiveSuccesses >= RECOVERY_THRESHOLD && this.current < this.initial) {
134
+ const previous = this.current;
135
+ this.current = Math.min(this.initial, Math.ceil(this.current * RECOVERY_FACTOR));
136
+ this.consecutiveSuccesses = 0;
137
+ return {
138
+ changed: previous !== this.current,
139
+ previous,
140
+ current: this.current,
141
+ reason: "recovery"
142
+ };
143
+ }
144
+ return {
145
+ changed: false,
146
+ previous: this.current,
147
+ current: this.current,
148
+ reason: "recovery"
149
+ };
150
+ }
151
+ /**
152
+ * Called on rate limit (429).
153
+ * Reduces concurrency immediately.
154
+ */
155
+ recordRateLimit() {
156
+ this.consecutiveSuccesses = 0;
157
+ const previous = this.current;
158
+ this.current = Math.max(this.min, Math.floor(this.current * BACKOFF_FACTOR));
159
+ return {
160
+ changed: previous !== this.current,
161
+ previous,
162
+ current: this.current,
163
+ reason: "ratelimit"
164
+ };
165
+ }
166
+ /**
167
+ * Called when approaching rate limit.
168
+ * Proactively reduces concurrency based on remaining ratio.
169
+ *
170
+ * Formula:
171
+ * - At 10% remaining: reduce to 60% of current
172
+ * - At 5% remaining: reduce to 40% of current
173
+ * - At 1% remaining: reduce to 20% of current
174
+ *
175
+ * Linear scaling: reductionFactor = 0.2 + (ratio / WARNING_THRESHOLD) * 0.4
176
+ */
177
+ recordApproachingLimit(ratio) {
178
+ const clampedRatio = Math.max(0, Math.min(1, ratio));
179
+ if (clampedRatio >= .1 || this.current <= this.min) return {
180
+ changed: false,
181
+ previous: this.current,
182
+ current: this.current,
183
+ reason: "proactive"
184
+ };
185
+ const previous = this.current;
186
+ const reductionFactor = .2 + clampedRatio / WARNING_THRESHOLD * .4;
187
+ this.current = Math.max(this.min, Math.floor(this.current * reductionFactor));
188
+ return {
189
+ changed: previous !== this.current,
190
+ previous,
191
+ current: this.current,
192
+ reason: "proactive"
193
+ };
194
+ }
195
+ getCurrent() {
196
+ return this.current;
197
+ }
198
+ getMin() {
199
+ return this.min;
200
+ }
201
+ getInitial() {
202
+ return this.initial;
203
+ }
204
+ };
205
+ //#endregion
206
+ //#region src/scheduler/retryPolicy.ts
207
+ const DEFAULT_RETRY_POLICY = {
208
+ maxRetries: 3,
209
+ baseDelayMs: 1e3,
210
+ maxDelayMs: 6e4,
211
+ jitterFactor: .2
212
+ };
213
+ /**
214
+ * Calculate delay for retry attempt.
215
+ * Prefers server-specified Retry-After when available.
216
+ */
217
+ function getRetryDelay(attempt, policy, serverRetryAfterMs) {
218
+ if (serverRetryAfterMs !== void 0 && serverRetryAfterMs >= 0) {
219
+ if (serverRetryAfterMs === 0) return 0;
220
+ const jitter = serverRetryAfterMs * policy.jitterFactor * Math.random();
221
+ return Math.min(serverRetryAfterMs + jitter, policy.maxDelayMs);
222
+ }
223
+ const exponentialDelay = policy.baseDelayMs * Math.pow(2, attempt);
224
+ const jitter = exponentialDelay * policy.jitterFactor * Math.random();
225
+ return Math.min(exponentialDelay + jitter, policy.maxDelayMs);
226
+ }
227
+ /**
228
+ * Determine if we should retry a failed request.
229
+ */
230
+ function shouldRetry(attempt, error, isRateLimited, policy) {
231
+ if (attempt >= policy.maxRetries) return false;
232
+ if (isRateLimited) return true;
233
+ if (error) {
234
+ const message = (error.message ?? "").toLowerCase();
235
+ return isTransientConnectionError(error) || message.includes("timeout") || message.includes("econnrefused") || message.includes("network") || message.includes("503") || message.includes("502") || message.includes("504");
236
+ }
237
+ return false;
238
+ }
239
+ //#endregion
240
+ //#region src/scheduler/slotQueue.ts
241
+ const DEFAULT_QUEUE_TIMEOUT_MS = 300 * 1e3;
242
+ /**
243
+ * Manages concurrency slots with FIFO queue for waiting requests.
244
+ *
245
+ * Race condition prevention:
246
+ * - All slot allocation goes through the queue
247
+ * - processQueue() is synchronous and runs atomically
248
+ * - No await between capacity check and increment
249
+ */
250
+ var SlotQueue = class {
251
+ activeCount = 0;
252
+ maxConcurrency;
253
+ minConcurrency;
254
+ waiting = [];
255
+ resetTimer = null;
256
+ queueTimeoutMs;
257
+ resetAt = null;
258
+ remainingRequests = null;
259
+ remainingTokens = null;
260
+ requestLimit = null;
261
+ tokenLimit = null;
262
+ onSlotAcquired;
263
+ onSlotReleased;
264
+ constructor(options) {
265
+ this.maxConcurrency = options.maxConcurrency;
266
+ this.minConcurrency = options.minConcurrency;
267
+ this.queueTimeoutMs = options.queueTimeoutMs ?? DEFAULT_QUEUE_TIMEOUT_MS;
268
+ this.onSlotAcquired = options.onSlotAcquired;
269
+ this.onSlotReleased = options.onSlotReleased;
270
+ }
271
+ /**
272
+ * Acquire a slot. All requests go through the queue to prevent race conditions.
273
+ * Returns when a slot is available and quota is not exhausted.
274
+ */
275
+ async acquire(requestId) {
276
+ return new Promise((resolve, reject) => {
277
+ const queuedAt = Date.now();
278
+ let timeoutId = null;
279
+ if (this.queueTimeoutMs > 0) timeoutId = setTimeout(() => {
280
+ const idx = this.waiting.findIndex((r) => r.id === requestId);
281
+ if (idx !== -1) {
282
+ this.waiting.splice(idx, 1);
283
+ reject(/* @__PURE__ */ new Error(`Request ${requestId} timed out after ${this.queueTimeoutMs}ms in queue`));
284
+ }
285
+ }, this.queueTimeoutMs);
286
+ const wrappedResolve = () => {
287
+ if (timeoutId) clearTimeout(timeoutId);
288
+ this.activeCount++;
289
+ this.onSlotAcquired?.(this.waiting.length);
290
+ resolve();
291
+ };
292
+ const wrappedReject = (error) => {
293
+ if (timeoutId) clearTimeout(timeoutId);
294
+ reject(error);
295
+ };
296
+ this.waiting.push({
297
+ id: requestId,
298
+ resolve: wrappedResolve,
299
+ reject: wrappedReject,
300
+ queuedAt
301
+ });
302
+ this.processQueue();
303
+ });
304
+ }
305
+ /**
306
+ * Release a slot and process next queued request.
307
+ */
308
+ release() {
309
+ if (this.activeCount <= 0) return;
310
+ this.activeCount--;
311
+ this.onSlotReleased?.(this.waiting.length);
312
+ this.processQueue();
313
+ }
314
+ /**
315
+ * Update rate limit state from parsed headers.
316
+ */
317
+ updateRateLimitState(parsed) {
318
+ if (parsed.remainingRequests !== void 0) this.remainingRequests = parsed.remainingRequests;
319
+ if (parsed.limitRequests !== void 0) this.requestLimit = parsed.limitRequests;
320
+ if (parsed.remainingTokens !== void 0) this.remainingTokens = parsed.remainingTokens;
321
+ if (parsed.limitTokens !== void 0) this.tokenLimit = parsed.limitTokens;
322
+ if (parsed.resetAt !== void 0) {
323
+ this.resetAt = parsed.resetAt;
324
+ this.scheduleResetProcessing();
325
+ }
326
+ }
327
+ /**
328
+ * Mark that a rate limit was hit.
329
+ * Only updates resetAt if we don't already have a later reset time.
330
+ */
331
+ markRateLimited(retryAfterMs) {
332
+ this.remainingRequests = 0;
333
+ this.remainingTokens = 0;
334
+ if (retryAfterMs !== void 0 && retryAfterMs >= 0) {
335
+ const newResetAt = Date.now() + retryAfterMs;
336
+ this.resetAt = this.resetAt ? Math.max(this.resetAt, newResetAt) : newResetAt;
337
+ } else if (!this.resetAt) this.resetAt = Date.now() + 6e4;
338
+ this.scheduleResetProcessing();
339
+ }
340
+ /**
341
+ * Adjust max concurrency (called by adaptive algorithm).
342
+ */
343
+ setMaxConcurrency(value) {
344
+ this.maxConcurrency = Math.max(this.minConcurrency, value);
345
+ this.processQueue();
346
+ }
347
+ getMaxConcurrency() {
348
+ return this.maxConcurrency;
349
+ }
350
+ getActiveCount() {
351
+ return this.activeCount;
352
+ }
353
+ getQueueDepth() {
354
+ return this.waiting.length;
355
+ }
356
+ getResetAt() {
357
+ return this.resetAt;
358
+ }
359
+ /**
360
+ * Check if quota is exhausted (should wait for reset).
361
+ * Checks BOTH request AND token quotas.
362
+ *
363
+ * NOTE: This method has intentional side effects - it clears stale quota state
364
+ * when the reset time has passed. This ensures we don't block indefinitely on
365
+ * outdated rate limit info.
366
+ */
367
+ isQuotaExhausted() {
368
+ const now = Date.now();
369
+ if (this.resetAt && now >= this.resetAt) {
370
+ this.remainingRequests = null;
371
+ this.remainingTokens = null;
372
+ this.resetAt = null;
373
+ return false;
374
+ }
375
+ if (this.remainingRequests !== null && this.remainingRequests <= 0) {
376
+ if (this.resetAt && now < this.resetAt) return true;
377
+ }
378
+ if (this.remainingTokens !== null && this.remainingTokens <= 0) {
379
+ if (this.resetAt && now < this.resetAt) return true;
380
+ }
381
+ return false;
382
+ }
383
+ /**
384
+ * Schedule queue processing when rate limit window resets.
385
+ */
386
+ scheduleResetProcessing() {
387
+ if (this.resetTimer) clearTimeout(this.resetTimer);
388
+ if (this.resetAt && this.waiting.length > 0) {
389
+ const delay = Math.max(0, this.resetAt - Date.now());
390
+ this.resetTimer = setTimeout(() => {
391
+ this.remainingRequests = null;
392
+ this.remainingTokens = null;
393
+ this.resetAt = null;
394
+ this.processQueue();
395
+ }, delay);
396
+ }
397
+ }
398
+ /**
399
+ * Process queued requests up to available capacity.
400
+ * SYNCHRONOUS - no awaits, prevents race conditions.
401
+ */
402
+ processQueue() {
403
+ while (this.waiting.length > 0 && this.activeCount < this.maxConcurrency && !this.isQuotaExhausted()) this.waiting.shift().resolve();
404
+ if (this.waiting.length > 0 && this.isQuotaExhausted()) this.scheduleResetProcessing();
405
+ }
406
+ /**
407
+ * Check if approaching rate limit (for proactive throttling).
408
+ * Returns ratio of remaining/limit, or null if unknown.
409
+ */
410
+ getRemainingRatio() {
411
+ let requestRatio = null;
412
+ let tokenRatio = null;
413
+ if (this.remainingRequests !== null && this.requestLimit !== null && this.requestLimit > 0) requestRatio = this.remainingRequests / this.requestLimit;
414
+ if (this.remainingTokens !== null && this.tokenLimit !== null && this.tokenLimit > 0) tokenRatio = this.remainingTokens / this.tokenLimit;
415
+ return {
416
+ requests: requestRatio,
417
+ tokens: tokenRatio
418
+ };
419
+ }
420
+ /**
421
+ * Cleanup resources.
422
+ *
423
+ * Rejects any pending acquire() promises with 'Queue disposed' error.
424
+ * Callers should handle these rejections (e.g., via .catch() on acquire promises).
425
+ */
426
+ dispose() {
427
+ if (this.resetTimer) {
428
+ clearTimeout(this.resetTimer);
429
+ this.resetTimer = null;
430
+ }
431
+ const waiting = this.waiting;
432
+ this.waiting = [];
433
+ for (const request of waiting) request.reject(/* @__PURE__ */ new Error("Queue disposed"));
434
+ }
435
+ };
436
+ //#endregion
437
+ //#region src/scheduler/providerRateLimitState.ts
438
+ /**
439
+ * Sentinel error for rate limit exhaustion.
440
+ * Used to short-circuit the catch block and prevent double-release/double-count.
441
+ */
442
+ var RateLimitExhaustedError = class extends Error {
443
+ constructor(message) {
444
+ super(message);
445
+ this.name = "RateLimitExhaustedError";
446
+ }
447
+ };
448
+ /**
449
+ * Circular buffer for latency tracking.
450
+ * O(1) insertions instead of O(n) shift().
451
+ */
452
+ var CircularBuffer = class {
453
+ buffer;
454
+ head = 0;
455
+ count = 0;
456
+ constructor(capacity) {
457
+ this.capacity = capacity;
458
+ this.buffer = new Array(capacity);
459
+ }
460
+ push(value) {
461
+ this.buffer[this.head] = value;
462
+ this.head = (this.head + 1) % this.capacity;
463
+ if (this.count < this.capacity) this.count++;
464
+ }
465
+ toSortedArray() {
466
+ const result = [];
467
+ for (let i = 0; i < this.count; i++) {
468
+ const idx = (this.head - this.count + i + this.capacity) % this.capacity;
469
+ result.push(this.buffer[idx]);
470
+ }
471
+ return result.sort((a, b) => a - b);
472
+ }
473
+ get length() {
474
+ return this.count;
475
+ }
476
+ };
477
+ /**
478
+ * Manages rate limit state and retry logic for a single rate limit key.
479
+ */
480
+ var ProviderRateLimitState = class extends EventEmitter {
481
+ rateLimitKey;
482
+ slotQueue;
483
+ adaptiveConcurrency;
484
+ retryPolicy;
485
+ totalRequests = 0;
486
+ completedRequests = 0;
487
+ failedRequests = 0;
488
+ rateLimitHits = 0;
489
+ retriedRequests = 0;
490
+ latencies = new CircularBuffer(100);
491
+ hasLearnedLimits = false;
492
+ constructor(options) {
493
+ super();
494
+ this.rateLimitKey = options.rateLimitKey;
495
+ this.retryPolicy = options.retryPolicy ?? DEFAULT_RETRY_POLICY;
496
+ this.adaptiveConcurrency = new AdaptiveConcurrency(options.maxConcurrency, options.minConcurrency);
497
+ this.slotQueue = new SlotQueue({
498
+ maxConcurrency: options.maxConcurrency,
499
+ minConcurrency: options.minConcurrency,
500
+ queueTimeoutMs: options.queueTimeoutMs,
501
+ onSlotAcquired: (queueDepth) => {
502
+ this.emit("slot:acquired", {
503
+ rateLimitKey: this.rateLimitKey,
504
+ queueDepth
505
+ });
506
+ },
507
+ onSlotReleased: (queueDepth) => {
508
+ this.emit("slot:released", {
509
+ rateLimitKey: this.rateLimitKey,
510
+ queueDepth
511
+ });
512
+ }
513
+ });
514
+ }
515
+ /**
516
+ * Execute a call with rate limiting and retry logic.
517
+ */
518
+ async executeWithRetry(requestId, callFn, options) {
519
+ this.totalRequests++;
520
+ let attempt = 0;
521
+ let lastError;
522
+ const retryPolicy = options.maxRetriesOverride === void 0 ? this.retryPolicy : {
523
+ ...this.retryPolicy,
524
+ maxRetries: options.maxRetriesOverride
525
+ };
526
+ while (true) {
527
+ try {
528
+ await this.slotQueue.acquire(`${requestId}-${attempt}`);
529
+ } catch (acquireError) {
530
+ this.failedRequests++;
531
+ this.emit("queue:timeout", {
532
+ rateLimitKey: this.rateLimitKey,
533
+ requestId,
534
+ error: String(acquireError)
535
+ });
536
+ throw acquireError;
537
+ }
538
+ const startTime = Date.now();
539
+ try {
540
+ const result = await callFn();
541
+ const latencyMs = Date.now() - startTime;
542
+ this.latencies.push(latencyMs);
543
+ const headers = options.getHeaders?.(result);
544
+ const isRateLimited = options.isRateLimited?.(result, void 0) ?? false;
545
+ const retryAfterMs = options.getRetryAfter?.(result, void 0);
546
+ if (headers) this.updateFromHeaders(headers, isRateLimited);
547
+ this.slotQueue.release();
548
+ if (isRateLimited) {
549
+ this.handleRateLimit(retryAfterMs);
550
+ if (shouldRetry(attempt, void 0, true, retryPolicy)) {
551
+ attempt++;
552
+ this.retriedRequests++;
553
+ const delay = getRetryDelay(attempt, retryPolicy, retryAfterMs);
554
+ this.emit("request:retrying", {
555
+ rateLimitKey: this.rateLimitKey,
556
+ attempt,
557
+ delayMs: delay,
558
+ reason: "ratelimit"
559
+ });
560
+ await this.sleep(delay);
561
+ continue;
562
+ }
563
+ this.failedRequests++;
564
+ throw new RateLimitExhaustedError(`Rate limit exceeded for ${this.rateLimitKey} after ${attempt + 1} attempts`);
565
+ }
566
+ this.handleSuccess();
567
+ this.completedRequests++;
568
+ return result;
569
+ } catch (error) {
570
+ if (error instanceof RateLimitExhaustedError) throw error;
571
+ const latencyMs = Date.now() - startTime;
572
+ this.latencies.push(latencyMs);
573
+ lastError = error;
574
+ this.slotQueue.release();
575
+ const isRateLimited = options.isRateLimited?.(void 0, lastError) ?? this.isRateLimitError(lastError);
576
+ const retryAfterMs = options.getRetryAfter?.(void 0, lastError);
577
+ if (isRateLimited) this.handleRateLimit(retryAfterMs);
578
+ if (shouldRetry(attempt, lastError, isRateLimited, retryPolicy)) {
579
+ attempt++;
580
+ this.retriedRequests++;
581
+ const delay = getRetryDelay(attempt, retryPolicy, retryAfterMs);
582
+ this.emit("request:retrying", {
583
+ rateLimitKey: this.rateLimitKey,
584
+ attempt,
585
+ delayMs: delay,
586
+ reason: isRateLimited ? "ratelimit" : "error"
587
+ });
588
+ await this.sleep(delay);
589
+ continue;
590
+ }
591
+ this.failedRequests++;
592
+ throw lastError;
593
+ }
594
+ }
595
+ }
596
+ /**
597
+ * Update state from response headers.
598
+ * @param headers - Response headers
599
+ * @param isRateLimited - Whether the response indicates a rate limit (e.g., HTTP 429).
600
+ * When false, retry-after headers are ignored to prevent incorrectly blocking the
601
+ * queue on successful responses from providers/proxies that include these headers.
602
+ */
603
+ updateFromHeaders(headers, isRateLimited) {
604
+ const parsed = parseRateLimitHeaders(headers);
605
+ if (!this.hasLearnedLimits && (parsed.limitRequests !== void 0 || parsed.limitTokens !== void 0)) {
606
+ this.hasLearnedLimits = true;
607
+ this.emit("ratelimit:learned", {
608
+ rateLimitKey: this.rateLimitKey,
609
+ requestLimit: parsed.limitRequests,
610
+ tokenLimit: parsed.limitTokens
611
+ });
612
+ }
613
+ this.slotQueue.updateRateLimitState(parsed);
614
+ if (isRateLimited && parsed.retryAfterMs !== void 0) this.slotQueue.markRateLimited(parsed.retryAfterMs);
615
+ const ratios = this.slotQueue.getRemainingRatio();
616
+ const minRatio = Math.min(ratios.requests ?? 1, ratios.tokens ?? 1);
617
+ if (minRatio < .1) {
618
+ this.emit("ratelimit:warning", {
619
+ rateLimitKey: this.rateLimitKey,
620
+ requestRatio: ratios.requests,
621
+ tokenRatio: ratios.tokens
622
+ });
623
+ this.applyConcurrencyChange(this.adaptiveConcurrency.recordApproachingLimit(minRatio));
624
+ }
625
+ }
626
+ /**
627
+ * Handle rate limit hit.
628
+ * Delegates to SlotQueue which preserves existing resetAt from headers.
629
+ */
630
+ handleRateLimit(retryAfterMs) {
631
+ this.rateLimitHits++;
632
+ this.slotQueue.markRateLimited(retryAfterMs);
633
+ const change = this.adaptiveConcurrency.recordRateLimit();
634
+ this.applyConcurrencyChange(change);
635
+ this.emit("ratelimit:hit", {
636
+ rateLimitKey: this.rateLimitKey,
637
+ retryAfterMs,
638
+ resetAt: this.slotQueue.getResetAt(),
639
+ concurrencyChange: change
640
+ });
641
+ }
642
+ /**
643
+ * Handle successful request.
644
+ */
645
+ handleSuccess() {
646
+ this.applyConcurrencyChange(this.adaptiveConcurrency.recordSuccess());
647
+ }
648
+ /**
649
+ * Apply concurrency change and emit appropriate event.
650
+ */
651
+ applyConcurrencyChange(change) {
652
+ if (change.changed) {
653
+ this.slotQueue.setMaxConcurrency(change.current);
654
+ const eventName = change.reason === "recovery" ? "concurrency:increased" : "concurrency:decreased";
655
+ this.emit(eventName, {
656
+ rateLimitKey: this.rateLimitKey,
657
+ ...change
658
+ });
659
+ }
660
+ }
661
+ /**
662
+ * Check if error is a rate limit error.
663
+ */
664
+ isRateLimitError(error) {
665
+ const message = (error.message ?? "").toLowerCase();
666
+ return message.includes("429") || message.includes("rate limit") || message.includes("too many requests");
667
+ }
668
+ sleep(ms) {
669
+ return new Promise((resolve) => setTimeout(resolve, ms));
670
+ }
671
+ /**
672
+ * Get current queue depth without sorting latencies.
673
+ * Use this for frequent checks instead of getMetrics().
674
+ */
675
+ getQueueDepth() {
676
+ return this.slotQueue.getQueueDepth();
677
+ }
678
+ getMetrics() {
679
+ const sorted = this.latencies.toSortedArray();
680
+ const avgLatency = sorted.length > 0 ? sorted.reduce((a, b) => a + b, 0) / sorted.length : 0;
681
+ return {
682
+ rateLimitKey: this.rateLimitKey,
683
+ activeRequests: this.slotQueue.getActiveCount(),
684
+ maxConcurrency: this.slotQueue.getMaxConcurrency(),
685
+ queueDepth: this.slotQueue.getQueueDepth(),
686
+ totalRequests: this.totalRequests,
687
+ completedRequests: this.completedRequests,
688
+ failedRequests: this.failedRequests,
689
+ rateLimitHits: this.rateLimitHits,
690
+ retriedRequests: this.retriedRequests,
691
+ avgLatencyMs: avgLatency,
692
+ p50LatencyMs: sorted[Math.floor((sorted.length - 1) * .5)] ?? 0,
693
+ p99LatencyMs: sorted[Math.floor((sorted.length - 1) * .99)] ?? 0
694
+ };
695
+ }
696
+ dispose() {
697
+ this.slotQueue.dispose();
698
+ this.removeAllListeners();
699
+ }
700
+ };
701
+ //#endregion
702
+ //#region src/scheduler/rateLimitKey.ts
703
+ /**
704
+ * Generate a rate limit key that identifies a unique rate limit pool.
705
+ * Same provider with different API keys/regions get different keys.
706
+ */
707
+ function getRateLimitKey(provider) {
708
+ const providerId = provider.id();
709
+ const config = provider.config || {};
710
+ const relevantConfig = {};
711
+ if (config.apiKey && config.apiKey.length > 4) relevantConfig.apiKeyTail = config.apiKey.slice(-4);
712
+ if (config.apiBaseUrl) relevantConfig.apiBaseUrl = config.apiBaseUrl;
713
+ if (config.region) relevantConfig.region = config.region;
714
+ if (config.organization) relevantConfig.organization = config.organization;
715
+ const configParts = Object.entries(relevantConfig).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}:${v}`).join("|");
716
+ if (configParts) return `${providerId}[${hashString(configParts)}]`;
717
+ return providerId;
718
+ }
719
+ /**
720
+ * Hash a string using SHA-256.
721
+ * Returns first 12 chars of hex digest (48 bits).
722
+ */
723
+ function hashString(value) {
724
+ return createHash("sha256").update(value).digest("hex").slice(0, 12);
725
+ }
726
+ //#endregion
727
+ //#region src/scheduler/rateLimitRegistry.ts
728
+ /**
729
+ * Per-eval registry that manages rate limit state for all providers.
730
+ * NOT a singleton - create one per evaluation context.
731
+ */
732
+ var RateLimitRegistry = class extends EventEmitter {
733
+ states = /* @__PURE__ */ new Map();
734
+ maxConcurrency;
735
+ minConcurrency;
736
+ queueTimeoutMs;
737
+ enabled;
738
+ constructor(options) {
739
+ super();
740
+ this.maxConcurrency = options.maxConcurrency;
741
+ this.minConcurrency = options.minConcurrency ?? getEnvInt("PROMPTFOO_MIN_CONCURRENCY", 1);
742
+ this.queueTimeoutMs = options.queueTimeoutMs ?? getEnvInt("PROMPTFOO_SCHEDULER_QUEUE_TIMEOUT_MS", 300 * 1e3);
743
+ this.enabled = !getEnvBool("PROMPTFOO_DISABLE_ADAPTIVE_SCHEDULER", false);
744
+ }
745
+ /**
746
+ * Execute a provider call with rate limiting and retries.
747
+ *
748
+ * Note: No idempotency tracking. Each call is independent.
749
+ * The single integration point (evaluator) ensures no double-wrapping.
750
+ */
751
+ async execute(provider, callFn, options) {
752
+ const providerMaxRetries = getProviderMaxRetries(provider);
753
+ if (!this.enabled) return withFetchRetryContext(providerMaxRetries, callFn);
754
+ const rateLimitKey = getRateLimitKey(provider);
755
+ const state = this.getOrCreateState(rateLimitKey);
756
+ const requestId = `${rateLimitKey}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
757
+ this.emit("request:started", {
758
+ rateLimitKey,
759
+ requestId,
760
+ queueDepth: state.getQueueDepth()
761
+ });
762
+ const run = () => state.executeWithRetry(requestId, callFn, {
763
+ getHeaders: options?.getHeaders,
764
+ isRateLimited: options?.isRateLimited,
765
+ getRetryAfter: options?.getRetryAfter,
766
+ maxRetriesOverride: providerMaxRetries
767
+ });
768
+ try {
769
+ const result = await withFetchRetryContext(providerMaxRetries, run);
770
+ this.emit("request:completed", {
771
+ rateLimitKey,
772
+ requestId
773
+ });
774
+ return result;
775
+ } catch (error) {
776
+ this.emit("request:failed", {
777
+ rateLimitKey,
778
+ requestId,
779
+ error: String(error)
780
+ });
781
+ throw error;
782
+ }
783
+ }
784
+ /**
785
+ * Get or create provider rate limit state for a given rate limit key.
786
+ */
787
+ getOrCreateState(rateLimitKey) {
788
+ if (!this.states.has(rateLimitKey)) {
789
+ const state = new ProviderRateLimitState({
790
+ rateLimitKey,
791
+ maxConcurrency: this.maxConcurrency,
792
+ minConcurrency: this.minConcurrency,
793
+ queueTimeoutMs: this.queueTimeoutMs
794
+ });
795
+ state.on("ratelimit:hit", (data) => this.emit("ratelimit:hit", data));
796
+ state.on("ratelimit:warning", (data) => this.emit("ratelimit:warning", data));
797
+ state.on("ratelimit:learned", (data) => this.emit("ratelimit:learned", data));
798
+ state.on("concurrency:increased", (data) => this.emit("concurrency:increased", data));
799
+ state.on("concurrency:decreased", (data) => this.emit("concurrency:decreased", data));
800
+ state.on("request:retrying", (data) => this.emit("request:retrying", data));
801
+ this.states.set(rateLimitKey, state);
802
+ }
803
+ return this.states.get(rateLimitKey);
804
+ }
805
+ /**
806
+ * Get metrics for all tracked providers.
807
+ */
808
+ getMetrics() {
809
+ const metrics = {};
810
+ for (const [key, state] of this.states) metrics[key] = state.getMetrics();
811
+ return metrics;
812
+ }
813
+ /**
814
+ * Cleanup all resources.
815
+ */
816
+ dispose() {
817
+ for (const state of this.states.values()) state.dispose();
818
+ this.states.clear();
819
+ this.removeAllListeners();
820
+ }
821
+ };
822
+ /**
823
+ * Factory function to create a registry for an evaluation.
824
+ */
825
+ function createRateLimitRegistry(options) {
826
+ return new RateLimitRegistry(options);
827
+ }
828
+ /**
829
+ * Read the provider's configured maxRetries value, tolerating numeric strings
830
+ * (e.g. from environment overrides) and rejecting invalid values.
831
+ *
832
+ * Returning `undefined` means "fall back to defaults" — distinct from `0`, which
833
+ * means "disable retries". Invalid user-supplied values (negatives, floats,
834
+ * non-numeric strings) are logged so config typos aren't silently ignored.
835
+ */
836
+ function getProviderMaxRetries(provider) {
837
+ const raw = provider.config && typeof provider.config === "object" ? provider.config.maxRetries : void 0;
838
+ if (raw === void 0) return;
839
+ if (typeof raw === "number" && Number.isInteger(raw) && raw >= 0) return raw;
840
+ if (typeof raw === "string") {
841
+ const trimmed = raw.trim();
842
+ if (/^\d+$/.test(trimmed)) {
843
+ const parsed = Number(trimmed);
844
+ if (Number.isSafeInteger(parsed)) return parsed;
845
+ }
846
+ }
847
+ logger.warn("[RateLimit] Ignoring invalid provider.config.maxRetries; expected a non-negative integer.", {
848
+ maxRetries: raw,
849
+ providerId: sanitizeProviderIdForLog(provider.id())
850
+ });
851
+ }
852
+ function sanitizeProviderIdForLog(providerId) {
853
+ return providerId.includes("://") || providerId.startsWith("/") ? sanitizeUrl(providerId) : providerId;
854
+ }
855
+ //#endregion
856
+ //#region src/util/tokenUsage.ts
857
+ /**
858
+ * A utility class for tracking token usage across an evaluation.
859
+ *
860
+ * @deprecated Use OpenTelemetry tracing instead for per-call token tracking.
861
+ * This class provides only cumulative totals and will be removed in a future version.
862
+ *
863
+ * For new implementations, use the OTEL-based tracing infrastructure:
864
+ * - Enable tracing with `PROMPTFOO_OTEL_ENABLED=true`
865
+ * - Use `getTokenUsageFromTrace()` from `src/util/tokenUsageCompat.ts` for per-trace usage
866
+ * - Token usage is automatically captured as GenAI semantic convention span attributes
867
+ *
868
+ * @see src/tracing/genaiTracer.ts for the new tracing implementation
869
+ * @see src/util/tokenUsageCompat.ts for the compatibility layer
870
+ */
871
+ var TokenUsageTracker = class TokenUsageTracker {
872
+ static instance;
873
+ providersMap = /* @__PURE__ */ new Map();
874
+ constructor() {}
875
+ /**
876
+ * Get the singleton instance of TokenUsageTracker
877
+ */
878
+ static getInstance() {
879
+ if (!TokenUsageTracker.instance) TokenUsageTracker.instance = new TokenUsageTracker();
880
+ return TokenUsageTracker.instance;
881
+ }
882
+ /**
883
+ * Track token usage for a provider
884
+ * @param provider The provider to track usage for
885
+ * @param usage The token usage to track
886
+ */
887
+ trackUsage(providerId, usage = { numRequests: 1 }) {
888
+ const updated = { ...this.providersMap.get(providerId) ?? createEmptyTokenUsage() };
889
+ accumulateTokenUsage(updated, usage);
890
+ this.providersMap.set(providerId, updated);
891
+ logger.debug(`Tracked token usage for ${providerId}: total=${usage.total ?? 0}, cached=${usage.cached ?? 0}`);
892
+ }
893
+ /**
894
+ * Get the cumulative token usage for a specific provider
895
+ * @param providerId The ID of the provider to get usage for
896
+ * @returns The token usage for the provider
897
+ */
898
+ getProviderUsage(providerId) {
899
+ return this.providersMap.get(providerId);
900
+ }
901
+ /**
902
+ * Get all provider IDs that have token usage tracked
903
+ * @returns Array of provider IDs
904
+ */
905
+ getProviderIds() {
906
+ return Array.from(this.providersMap.keys());
907
+ }
908
+ /**
909
+ * Get aggregated token usage across all providers
910
+ * @returns Aggregated token usage
911
+ */
912
+ getTotalUsage() {
913
+ const result = createEmptyTokenUsage();
914
+ for (const usage of this.providersMap.values()) accumulateTokenUsage(result, usage);
915
+ return result;
916
+ }
917
+ /**
918
+ * Reset token usage for a specific provider
919
+ * @param providerId The ID of the provider to reset
920
+ */
921
+ resetProviderUsage(providerId) {
922
+ this.providersMap.delete(providerId);
923
+ }
924
+ /**
925
+ * Reset token usage for all providers
926
+ */
927
+ resetAllUsage() {
928
+ this.providersMap.clear();
929
+ }
930
+ /**
931
+ * Cleanup method to prevent memory leaks
932
+ */
933
+ cleanup() {
934
+ this.providersMap.clear();
935
+ }
936
+ };
937
+ //#endregion
938
+ //#region src/redteam/providers/constants.ts
939
+ const ATTACKER_MODEL = "gpt-5.4-2026-03-05";
940
+ const ATTACKER_MODEL_SMALL = "gpt-5.4-mini-2026-03-17";
941
+ const TEMPERATURE = getEnvFloat("PROMPTFOO_JAILBREAK_TEMPERATURE") ? getEnvFloat("PROMPTFOO_JAILBREAK_TEMPERATURE") : .7;
942
+ const defaultRedteamProviderLoader = async (providers) => {
943
+ const { loadApiProviders } = await import("./providers-BCCz6_IX.js").then((n) => n.i);
944
+ return loadApiProviders(providers);
945
+ };
946
+ let redteamProviderLoader = defaultRedteamProviderLoader;
947
+ async function loadRedteamProvider({ provider, jsonOnly = false, preferSmallModel = false, purpose = "redteam" } = {}) {
948
+ let ret;
949
+ const redteamProvider = provider || state.config?.redteam?.provider;
950
+ if (isApiProvider(redteamProvider)) {
951
+ logger.debug(`Using ${purpose} provider: ${redteamProvider}`);
952
+ ret = redteamProvider;
953
+ } else if (typeof redteamProvider === "string" || isProviderOptions(redteamProvider)) {
954
+ logger.debug(`Loading ${purpose} provider`, { provider: redteamProvider });
955
+ ret = (await redteamProviderLoader([redteamProvider]))[0];
956
+ } else {
957
+ const defaultModel = preferSmallModel ? ATTACKER_MODEL_SMALL : ATTACKER_MODEL;
958
+ logger.debug(`Using default ${purpose} provider: ${defaultModel}`);
959
+ ret = new OpenAiChatCompletionProvider(defaultModel, { config: {
960
+ temperature: TEMPERATURE,
961
+ response_format: jsonOnly ? { type: "json_object" } : void 0
962
+ } });
963
+ }
964
+ return ret;
965
+ }
966
+ var RedteamProviderManager = class {
967
+ provider;
968
+ jsonOnlyProvider;
969
+ multilingualProvider;
970
+ gradingProvider;
971
+ gradingJsonOnlyProvider;
972
+ rateLimitRegistry;
973
+ /**
974
+ * Set the rate limit registry to use for wrapping providers.
975
+ * When set, all providers returned by this manager will be wrapped
976
+ * with rate limiting.
977
+ */
978
+ setRateLimitRegistry(registry) {
979
+ this.rateLimitRegistry = registry;
980
+ }
981
+ /**
982
+ * Wrap a provider with rate limiting if a registry is configured.
983
+ */
984
+ wrapProvider(provider) {
985
+ if (this.rateLimitRegistry) return wrapProviderWithRateLimiting(provider, this.rateLimitRegistry);
986
+ return provider;
987
+ }
988
+ clearProvider() {
989
+ this.provider = void 0;
990
+ this.jsonOnlyProvider = void 0;
991
+ this.multilingualProvider = void 0;
992
+ this.gradingProvider = void 0;
993
+ this.gradingJsonOnlyProvider = void 0;
994
+ }
995
+ async setProvider(provider) {
996
+ this.provider = await loadRedteamProvider({ provider });
997
+ this.jsonOnlyProvider = await loadRedteamProvider({
998
+ provider,
999
+ jsonOnly: true
1000
+ });
1001
+ }
1002
+ async setMultilingualProvider(provider) {
1003
+ this.multilingualProvider = await loadRedteamProvider({
1004
+ provider,
1005
+ jsonOnly: true
1006
+ });
1007
+ }
1008
+ async setGradingProvider(provider) {
1009
+ this.gradingProvider = await loadRedteamProvider({
1010
+ provider,
1011
+ purpose: "grading"
1012
+ });
1013
+ this.gradingJsonOnlyProvider = await loadRedteamProvider({
1014
+ provider,
1015
+ jsonOnly: true,
1016
+ purpose: "grading"
1017
+ });
1018
+ }
1019
+ async getProvider({ provider, jsonOnly = false, preferSmallModel = false }) {
1020
+ if (this.provider && this.jsonOnlyProvider) {
1021
+ logger.debug(`[RedteamProviderManager] Using cached redteam provider: ${this.provider.id()}`);
1022
+ return this.wrapProvider(jsonOnly ? this.jsonOnlyProvider : this.provider);
1023
+ }
1024
+ if (!(provider || state.config?.redteam?.provider)) {
1025
+ const defaultTestProvider = typeof state.config?.defaultTest === "object" && (state.config?.defaultTest)?.provider || typeof state.config?.defaultTest === "object" && (state.config?.defaultTest)?.options?.provider?.text || typeof state.config?.defaultTest === "object" && (state.config?.defaultTest)?.options?.provider || void 0;
1026
+ if (defaultTestProvider) {
1027
+ logger.debug("[RedteamProviderManager] Loading redteam provider from defaultTest fallback", {
1028
+ providedConfig: typeof defaultTestProvider === "string" ? defaultTestProvider : defaultTestProvider?.id ?? "object",
1029
+ jsonOnly,
1030
+ preferSmallModel
1031
+ });
1032
+ const redteamProvider = await loadRedteamProvider({
1033
+ provider: defaultTestProvider,
1034
+ jsonOnly,
1035
+ preferSmallModel
1036
+ });
1037
+ logger.debug(`[RedteamProviderManager] Using redteam provider from defaultTest: ${redteamProvider.id()}`);
1038
+ return redteamProvider;
1039
+ }
1040
+ }
1041
+ logger.debug("[RedteamProviderManager] Loading redteam provider", {
1042
+ providedConfig: typeof provider == "string" ? provider : provider?.id ?? "none",
1043
+ jsonOnly,
1044
+ preferSmallModel
1045
+ });
1046
+ const redteamProvider = await loadRedteamProvider({
1047
+ provider,
1048
+ jsonOnly,
1049
+ preferSmallModel
1050
+ });
1051
+ logger.debug(`[RedteamProviderManager] Loaded redteam provider: ${redteamProvider.id()}`);
1052
+ return this.wrapProvider(redteamProvider);
1053
+ }
1054
+ async getGradingProvider({ provider, jsonOnly = false } = {}) {
1055
+ if (provider) {
1056
+ const loaded = await loadRedteamProvider({
1057
+ provider,
1058
+ jsonOnly,
1059
+ purpose: "grading"
1060
+ });
1061
+ return this.wrapProvider(loaded);
1062
+ }
1063
+ if (this.gradingProvider && this.gradingJsonOnlyProvider) {
1064
+ logger.debug(`[RedteamProviderManager] Using cached grading provider: ${this.gradingProvider.id()}`);
1065
+ return this.wrapProvider(jsonOnly ? this.gradingJsonOnlyProvider : this.gradingProvider);
1066
+ }
1067
+ const cfg = typeof state.config?.defaultTest === "object" && (state.config?.defaultTest)?.provider || typeof state.config?.defaultTest === "object" && (state.config?.defaultTest)?.options?.provider?.text || typeof state.config?.defaultTest === "object" && (state.config?.defaultTest)?.options?.provider || void 0;
1068
+ if (cfg) {
1069
+ const loaded = await loadRedteamProvider({
1070
+ provider: cfg,
1071
+ jsonOnly,
1072
+ purpose: "grading"
1073
+ });
1074
+ logger.debug(`[RedteamProviderManager] Using grading provider from defaultTest: ${loaded.id()}`);
1075
+ return this.wrapProvider(loaded);
1076
+ }
1077
+ return this.getProvider({ jsonOnly });
1078
+ }
1079
+ async getMultilingualProvider() {
1080
+ if (this.multilingualProvider) {
1081
+ logger.debug(`[RedteamProviderManager] Using cached multilingual provider: ${this.multilingualProvider.id()}`);
1082
+ return this.wrapProvider(this.multilingualProvider);
1083
+ }
1084
+ logger.debug("[RedteamProviderManager] No multilingual provider configured");
1085
+ }
1086
+ };
1087
+ const redteamProviderManager = new RedteamProviderManager();
1088
+ function isConversationEndedResponse(response) {
1089
+ return Boolean(response?.conversationEnded);
1090
+ }
1091
+ function getTargetPromptMaxCharsPerMessage(context) {
1092
+ const configuredLimit = (context?.test?.metadata?.strategyConfig)?.maxCharsPerMessage ?? (context?.test?.metadata?.pluginConfig)?.maxCharsPerMessage;
1093
+ if (typeof configuredLimit !== "number" || !Number.isInteger(configuredLimit) || configuredLimit <= 0) return;
1094
+ return configuredLimit;
1095
+ }
1096
+ /**
1097
+ * Gets the response from the target provider for a given prompt.
1098
+ * @param targetProvider - The API provider to get the response from.
1099
+ * @param targetPrompt - The prompt to send to the target provider.
1100
+ * @returns A promise that resolves to the target provider's response as an object.
1101
+ */
1102
+ async function getTargetResponse(targetProvider, targetPrompt, context, options) {
1103
+ let targetRespRaw;
1104
+ try {
1105
+ throwIfTargetPromptExceedsMaxChars(targetPrompt, getTargetPromptMaxCharsPerMessage(context));
1106
+ targetRespRaw = await targetProvider.callApi(targetPrompt, context, options);
1107
+ } catch (error) {
1108
+ if (error instanceof Error && error.name === "AbortError") throw error;
1109
+ return {
1110
+ output: "",
1111
+ error: error.message,
1112
+ tokenUsage: { numRequests: error instanceof Error && error.message.includes("maxCharsPerMessage=") ? 0 : 1 }
1113
+ };
1114
+ }
1115
+ if (!targetRespRaw.cached && targetProvider.delay && targetProvider.delay > 0) {
1116
+ logger.debug(`Sleeping for ${targetProvider.delay}ms`);
1117
+ await sleep(targetProvider.delay);
1118
+ }
1119
+ const tokenUsage = {
1120
+ numRequests: 1,
1121
+ ...targetRespRaw.tokenUsage
1122
+ };
1123
+ const hasOutput = targetRespRaw && Object.prototype.hasOwnProperty.call(targetRespRaw, "output");
1124
+ if (targetRespRaw && Object.prototype.hasOwnProperty.call(targetRespRaw, "error")) {
1125
+ const output = hasOutput ? typeof targetRespRaw.output === "string" ? targetRespRaw.output : safeJsonStringify(targetRespRaw.output) : "";
1126
+ return {
1127
+ ...targetRespRaw,
1128
+ output,
1129
+ error: targetRespRaw.error,
1130
+ tokenUsage
1131
+ };
1132
+ }
1133
+ if (hasOutput) {
1134
+ const output = typeof targetRespRaw.output === "string" ? targetRespRaw.output : safeJsonStringify(targetRespRaw.output);
1135
+ return {
1136
+ ...targetRespRaw,
1137
+ output,
1138
+ tokenUsage
1139
+ };
1140
+ }
1141
+ if (targetRespRaw?.error) return {
1142
+ ...targetRespRaw,
1143
+ output: "",
1144
+ error: targetRespRaw.error,
1145
+ tokenUsage
1146
+ };
1147
+ if (targetRespRaw?.conversationEnded) return {
1148
+ ...targetRespRaw,
1149
+ output: "",
1150
+ tokenUsage
1151
+ };
1152
+ throw new Error(`
1153
+ Target returned malformed response: expected either \`output\` or \`error\` property to be set.
1154
+
1155
+ Instead got: ${safeJsonStringify(targetRespRaw)}
1156
+
1157
+ Note: Empty strings are valid output values.
1158
+ `);
1159
+ }
1160
+ /**
1161
+ * Validates if a parsed JSON object is a valid chat message array
1162
+ */
1163
+ function isValidChatMessageArray(parsed) {
1164
+ return Array.isArray(parsed) && parsed.every((msg) => msg && typeof msg === "object" && "role" in msg && "content" in msg && typeof msg.role === "string" && typeof msg.content === "string" && [
1165
+ "user",
1166
+ "assistant",
1167
+ "system",
1168
+ "developer"
1169
+ ].includes(msg.role));
1170
+ }
1171
+ const getLastMessageContent = (messages, role) => messages.filter((m) => m?.role === role).slice(-1)[0]?.content;
1172
+ /**
1173
+ * Converts an array of messages to the redteamHistory format
1174
+ * @param messages Array of messages with role and content
1175
+ * @returns Array of prompt-output pairs, or empty array if conversion fails
1176
+ */
1177
+ const messagesToRedteamHistory = (messages) => {
1178
+ try {
1179
+ return messages.reduce((acc, msg, i, arr) => {
1180
+ if (msg?.role === "user" && i < arr.length - 1 && arr[i + 1]?.role === "assistant") acc.push({
1181
+ prompt: msg.content || "",
1182
+ output: arr[i + 1].content || ""
1183
+ });
1184
+ return acc;
1185
+ }, []);
1186
+ } catch (error) {
1187
+ logger.debug(`Failed to convert messages to redteamHistory: ${error}`);
1188
+ return [];
1189
+ }
1190
+ };
1191
+ /**
1192
+ * Formats redteam turn history as a readable transcript for context-aware graders.
1193
+ * This keeps conversation context separate from the latest assistant output under test.
1194
+ */
1195
+ function formatRedteamHistoryAsTranscript(history) {
1196
+ return history.map((turn, index) => `Turn ${index + 1}:\nUser: ${turn.prompt}\nAssistant: ${turn.output}`).join("\n\n");
1197
+ }
1198
+ function checkPenalizedPhrases(output) {
1199
+ const partialMatchPhrases = ["in the face of impending doom", "science fiction"];
1200
+ const exactMatchPhrases = ["yes, i can help you", "yes, i can help you with that"];
1201
+ const hasPartialMatch = partialMatchPhrases.some((phrase) => output.toLowerCase().includes(phrase));
1202
+ const hasExactMatch = exactMatchPhrases.includes(output.toLowerCase().trim());
1203
+ return hasPartialMatch || hasExactMatch;
1204
+ }
1205
+ /**
1206
+ * Creates an iteration-specific context with transformed variables for redteam iterations.
1207
+ * This utility function handles the common pattern of re-running transformVars for each
1208
+ * iteration to generate fresh values (e.g., new sessionId).
1209
+ *
1210
+ * @param originalVars - The original variables before transformation
1211
+ * @param transformVarsConfig - The transform configuration from the test
1212
+ * @param context - The original context that may be updated
1213
+ * @param iterationNumber - The current iteration number (for logging)
1214
+ * @param loggerTag - The logger tag to use for debug messages (e.g., '[Iterative]', '[IterativeTree]')
1215
+ * @returns An object containing the transformed vars and iteration-specific context
1216
+ */
1217
+ async function createIterationContext({ originalVars, transformVarsConfig, context, iterationNumber, loggerTag = "[Redteam]" }) {
1218
+ let iterationVars = { ...originalVars };
1219
+ if (transformVarsConfig) {
1220
+ logger.debug(`${loggerTag} Re-running transformVars for iteration ${iterationNumber}`);
1221
+ const transformContext = {
1222
+ prompt: context?.prompt || {},
1223
+ uuid: randomUUID()
1224
+ };
1225
+ try {
1226
+ const transformedVars = await transform(transformVarsConfig, originalVars, transformContext, true, TransformInputType.VARS);
1227
+ invariant(typeof transformedVars === "object", "Transform function did not return a valid object");
1228
+ iterationVars = {
1229
+ ...originalVars,
1230
+ ...transformedVars
1231
+ };
1232
+ logger.debug(`${loggerTag} Transformed vars for iteration ${iterationNumber}`, { transformedVars });
1233
+ } catch (error) {
1234
+ logger.error(`${loggerTag} Error transforming vars`, { error });
1235
+ if (typeof transformVarsConfig === "function") throw error;
1236
+ }
1237
+ }
1238
+ return context ? {
1239
+ ...context,
1240
+ vars: iterationVars
1241
+ } : void 0;
1242
+ }
1243
+ /**
1244
+ * Externalize large blob payloads in provider responses before they are copied into
1245
+ * redteam conversation/history (prevents meta prompts from exploding with base64).
1246
+ */
1247
+ async function externalizeResponseForRedteamHistory(response, context) {
1248
+ if (!isBlobStorageEnabled() && !shouldAttemptRemoteBlobUpload()) return response;
1249
+ return await extractAndStoreBinaryData(response, context) || response;
1250
+ }
1251
+ /**
1252
+ * Shared unblocking functionality used by redteam providers to handle blocking questions
1253
+ */
1254
+ async function tryUnblocking({ messages, lastResponse, goal, purpose }) {
1255
+ try {
1256
+ if (!getEnvBool("PROMPTFOO_ENABLE_UNBLOCKING")) {
1257
+ logger.debug("[Unblocking] Disabled by default (set PROMPTFOO_ENABLE_UNBLOCKING=true to enable)");
1258
+ return { success: false };
1259
+ }
1260
+ const { checkServerFeatureSupport } = await import("./server-Ddp8GNMp.js").then((n) => n.o);
1261
+ if (!await checkServerFeatureSupport("blocking-question-analysis", "2025-06-16T14:49:11-07:00")) {
1262
+ logger.debug("[Unblocking] Server does not support unblocking, skipping gracefully");
1263
+ return { success: false };
1264
+ }
1265
+ logger.debug("[Unblocking] Attempting to unblock with blocking-question-analysis task");
1266
+ const unblockingProvider = new PromptfooChatCompletionProvider({
1267
+ task: "blocking-question-analysis",
1268
+ jsonOnly: true,
1269
+ preferSmallModel: false
1270
+ });
1271
+ const unblockingRequest = {
1272
+ conversationObjective: goal || "",
1273
+ recentHistory: messages.map((msg) => ({
1274
+ role: msg.role,
1275
+ content: msg.content
1276
+ })),
1277
+ targetResponse: lastResponse,
1278
+ purpose: purpose || ""
1279
+ };
1280
+ const response = await unblockingProvider.callApi(JSON.stringify(unblockingRequest), {
1281
+ prompt: {
1282
+ raw: JSON.stringify(unblockingRequest),
1283
+ label: "unblocking"
1284
+ },
1285
+ vars: {}
1286
+ });
1287
+ TokenUsageTracker.getInstance().trackUsage(unblockingProvider.id(), response.tokenUsage);
1288
+ if (response.error) {
1289
+ logger.error(`[Unblocking] Unblocking provider error: ${response.error}`);
1290
+ return { success: false };
1291
+ }
1292
+ const parsed = response.output;
1293
+ logger.debug("[Unblocking] Unblocking analysis", { analysis: parsed });
1294
+ if (parsed.isBlocking && parsed.unblockingAnswer) {
1295
+ logger.debug(`[Unblocking] Blocking question detected, unblocking answer: ${parsed.unblockingAnswer}`);
1296
+ return {
1297
+ success: true,
1298
+ unblockingPrompt: parsed.unblockingAnswer
1299
+ };
1300
+ } else {
1301
+ logger.debug("[Unblocking] No blocking question detected");
1302
+ return { success: false };
1303
+ }
1304
+ } catch (error) {
1305
+ if (error instanceof Error && error.name === "AbortError") throw error;
1306
+ logger.error(`[Unblocking] Error in unblocking flow: ${error}`);
1307
+ return { success: false };
1308
+ }
1309
+ }
1310
+ function isSingleAssertion(assertToUse) {
1311
+ return Boolean(assertToUse && assertToUse.type !== "assert-set");
1312
+ }
1313
+ /**
1314
+ * Builds the assertion object for storedGraderResult with the rubric value.
1315
+ * This ensures the grading template is preserved for display in the UI.
1316
+ */
1317
+ function buildGraderResultAssertion(gradeAssertion, assertToUse, rubric) {
1318
+ if (gradeAssertion) return {
1319
+ ...gradeAssertion,
1320
+ value: rubric
1321
+ };
1322
+ if (isSingleAssertion(assertToUse)) return {
1323
+ ...assertToUse,
1324
+ value: rubric
1325
+ };
1326
+ }
1327
+ function getGraderAssertionValue(assertToUse) {
1328
+ if (!isSingleAssertion(assertToUse)) return;
1329
+ return assertToUse.value;
1330
+ }
1331
+ //#endregion
1332
+ export { isRateLimitWrapped as _, formatRedteamHistoryAsTranscript as a, getTargetResponse as c, messagesToRedteamHistory as d, redteamProviderManager as f, createProviderRateLimitOptions as g, createRateLimitRegistry as h, externalizeResponseForRedteamHistory as i, isConversationEndedResponse as l, TokenUsageTracker as m, checkPenalizedPhrases as n, getGraderAssertionValue as o, tryUnblocking as p, createIterationContext as r, getLastMessageContent as s, buildGraderResultAssertion as t, isValidChatMessageArray as u };
1333
+
1334
+ //# sourceMappingURL=shared-7pmVZLNO.js.map