promptfoo 0.125.0 → 0.125.1
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.
- package/README.md +3 -3
- package/dist/src/accounts-BOxNYxVN.js +229 -0
- package/dist/src/accounts-BezXLdAW.cjs +276 -0
- package/dist/src/accounts-CPISMNlh.js +227 -0
- package/dist/src/accounts-vJBPs89d.js +222 -0
- package/dist/src/agentWorkspace-Bom7SpF2.js +592 -0
- package/dist/src/agentWorkspace-CEomAcws.cjs +619 -0
- package/dist/src/agentWorkspace-DPtMLrlI.js +593 -0
- package/dist/src/agentWorkspace-DkAeEYLz.js +592 -0
- package/dist/src/agentic-utils-121v7mJo.js +197 -0
- package/dist/src/agentic-utils-CBWD_rcd.cjs +237 -0
- package/dist/src/agentic-utils-D8wyQwPG.js +198 -0
- package/dist/src/agentic-utils-EP1QkQCs.js +197 -0
- package/dist/src/agents-Br3ah8iA.js +778 -0
- package/dist/src/agents-C5wj_UTv.js +777 -0
- package/dist/src/agents-C9Efp4mC.js +266 -0
- package/dist/src/agents-CQYwaVCO.js +267 -0
- package/dist/src/agents-CjCd4Vo8.js +777 -0
- package/dist/src/agents-DRWiCHYz.js +266 -0
- package/dist/src/agents-F2rhx0iL.cjs +266 -0
- package/dist/src/agents-RTYyy69h.cjs +777 -0
- package/dist/src/agents-api-CY72O86e.js +711 -0
- package/dist/src/agents-api-CsSsC21b.js +710 -0
- package/dist/src/agents-api-DN-ibDc8.js +710 -0
- package/dist/src/agents-api-cNDsCCv1.cjs +710 -0
- package/dist/src/ai.studio-Bj6Dyi6o.js +2 -0
- package/dist/src/ai.studio-C-e0LzyW.js +369 -0
- package/dist/src/ai.studio-CR8M6Aqf.cjs +391 -0
- package/dist/src/ai.studio-YKk7F0tv.js +374 -0
- package/dist/src/aimlapi-BGunsuTu.js +30 -0
- package/dist/src/aimlapi-BkzcfBsL.js +29 -0
- package/dist/src/aimlapi-DXFcEdP8.js +28 -0
- package/dist/src/aimlapi-r-8iCcAw.cjs +29 -0
- package/dist/src/anthropicMessages-7-YNRgQR.js +114 -0
- package/dist/src/anthropicMessages-C8m9Whrd.cjs +114 -0
- package/dist/src/anthropicMessages-DS1vXD0f.js +115 -0
- package/dist/src/anthropicMessages-DmvGkz-0.js +114 -0
- package/dist/src/app/assets/index-CrdXWTXm.js +392 -0
- package/dist/src/app/browser-inventory.json +4 -4
- package/dist/src/app/index.html +1 -1
- package/dist/src/audio-BLgFgyw-.cjs +104 -0
- package/dist/src/audio-C2sibT7Q.js +104 -0
- package/dist/src/audio-DXEXb03H.js +104 -0
- package/dist/src/audio-TkvojpwO.js +105 -0
- package/dist/src/authoritativeMarkupInjection-BAT9B-Wj.js +79 -0
- package/dist/src/authoritativeMarkupInjection-B_yHETKT.js +78 -0
- package/dist/src/authoritativeMarkupInjection-BfjecQ3Q.cjs +78 -0
- package/dist/src/authoritativeMarkupInjection-D-hDKrhD.js +78 -0
- package/dist/src/aws-B_9unI_-.js +1149 -0
- package/dist/src/aws-D0FY3qkc.js +2433 -0
- package/dist/src/aws-Dh1-a90n.js +2433 -0
- package/dist/src/aws-qskKGczY.cjs +2454 -0
- package/dist/src/base-CaWlBkVz.js +462 -0
- package/dist/src/base-CcViNwVs.js +255 -0
- package/dist/src/base-CsVbPJkU.cjs +467 -0
- package/dist/src/base-DNK9py25.js +255 -0
- package/dist/src/base-DlH5tjEZ.js +463 -0
- package/dist/src/base-DyLOZ_iX.js +256 -0
- package/dist/src/base-RRYXfG7l.cjs +305 -0
- package/dist/src/base-oXVgvtVn.js +462 -0
- package/dist/src/bedrock-BP17ZXbR.cjs +2 -0
- package/dist/src/bedrock-CsjM1dOt.js +1300 -0
- package/dist/src/bedrock-CzPwj8GO.js +1 -0
- package/dist/src/bedrock-eGXZw8oh.js +1 -0
- package/dist/src/bedrock-tSWjmXdj.js +2 -0
- package/dist/src/bestOfN-BQ93nUKV.js +160 -0
- package/dist/src/bestOfN-ByGGwlcb.cjs +161 -0
- package/dist/src/bestOfN-CbP7csHr.js +159 -0
- package/dist/src/bestOfN-xn6i2Xs2.js +159 -0
- package/dist/src/cache-CHq9hPz9.js +2 -0
- package/dist/src/cache-D-9eZN3I.js +754 -0
- package/dist/src/cache-DSm6t1MZ.js +741 -0
- package/dist/src/cache-DeF5zIEN.js +782 -0
- package/dist/src/cache-iG87oYan.cjs +856 -0
- package/dist/src/cerebras-CTtM4yMH.js +98 -0
- package/dist/src/cerebras-CogcJ3ce.cjs +97 -0
- package/dist/src/cerebras-DmkRypTh.js +97 -0
- package/dist/src/cerebras-GUp0B8JY.js +97 -0
- package/dist/src/chat-B4ihd3fw.js +226 -0
- package/dist/src/chat-B9cAQ_rS.js +227 -0
- package/dist/src/chat-BU7EB4R-.cjs +76 -0
- package/dist/src/chat-C8yxJ2-s.cjs +226 -0
- package/dist/src/chat-ClTFM3qq.js +934 -0
- package/dist/src/chat-Cnq0Is68.js +123 -0
- package/dist/src/chat-CwrurR57.cjs +987 -0
- package/dist/src/chat-D0lsojPv.js +124 -0
- package/dist/src/chat-D7_8yFIx.js +76 -0
- package/dist/src/chat-DCoETlLG.js +226 -0
- package/dist/src/chat-DHE7xaTR.js +76 -0
- package/dist/src/chat-DmhT6rz2.cjs +123 -0
- package/dist/src/chat-DvfMe8KI.js +123 -0
- package/dist/src/chat-DwP5kVnl.js +935 -0
- package/dist/src/chat-MB7U-QE2.js +77 -0
- package/dist/src/chat-zCWuBKAj.js +934 -0
- package/dist/src/claude-agent-sdk-23bIVI75.js +999 -0
- package/dist/src/claude-agent-sdk-BACpnIJi.cjs +1005 -0
- package/dist/src/claude-agent-sdk-BlYlmcEr.js +999 -0
- package/dist/src/claude-agent-sdk-Cr-jqJZl.js +1000 -0
- package/dist/src/client-BktbiPx9.cjs +357 -0
- package/dist/src/client-CjztEBmW.js +351 -0
- package/dist/src/client-mRs2UvH9.js +351 -0
- package/dist/src/client-uCz0ydjC.js +352 -0
- package/dist/src/cloud-BtYF555L.js +2 -0
- package/dist/src/cloud-CVSUEmAy.js +287 -0
- package/dist/src/cloud-D7Ifb-Fl.js +599 -0
- package/dist/src/cloud-DB5oK5NX.cjs +666 -0
- package/dist/src/cloud-ecu989Em.js +657 -0
- package/dist/src/cloud-ramjGURF.js +599 -0
- package/dist/src/cloudflare-ai-BfDkIjO8.js +133 -0
- package/dist/src/cloudflare-ai-D9HaXz1M.js +134 -0
- package/dist/src/cloudflare-ai-HrD5WUK8.js +132 -0
- package/dist/src/cloudflare-ai-Qdj8aKP2.cjs +133 -0
- package/dist/src/cloudflare-gateway-C81uKETQ.js +276 -0
- package/dist/src/cloudflare-gateway-CX5Z9X0k.js +276 -0
- package/dist/src/cloudflare-gateway-DW-og8gb.js +277 -0
- package/dist/src/cloudflare-gateway-iRyXo9n2.cjs +276 -0
- package/dist/src/codex-app-server-BFIrSgdy.js +2155 -0
- package/dist/src/codex-app-server-By1eDVD4.js +2 -0
- package/dist/src/codex-app-server-DKsF4qmY.js +2156 -0
- package/dist/src/codex-app-server-n7n4uZzC.cjs +2162 -0
- package/dist/src/codex-app-server-xAoELVxu.js +2155 -0
- package/dist/src/codex-sdk-C2ZLxa6r.js +1552 -0
- package/dist/src/codex-sdk-CzG02tQt.cjs +1588 -0
- package/dist/src/codex-sdk-DNxAOhiV.js +2 -0
- package/dist/src/codex-sdk-DT3aQezK.js +1557 -0
- package/dist/src/codex-sdk-pw9DpcJP.js +1557 -0
- package/dist/src/codex-security-B0bLmXJF.js +406 -0
- package/dist/src/codex-security-BhYs-3iY.js +406 -0
- package/dist/src/codex-security-DQcOfxYW.js +407 -0
- package/dist/src/codex-security-DsCWr6GZ.cjs +411 -0
- package/dist/src/cometapi-B16asPLX.cjs +55 -0
- package/dist/src/cometapi-MgTbZA_H.js +53 -0
- package/dist/src/cometapi-i33vKzPV.js +55 -0
- package/dist/src/cometapi-wK2UWK0X.js +56 -0
- package/dist/src/compatible-COj8ZCy9.js +24 -0
- package/dist/src/compatible-CRSsIUGb.cjs +24 -0
- package/dist/src/compatible-Dy1vCcNF.js +25 -0
- package/dist/src/compatible-aUItQrpk.js +24 -0
- package/dist/src/completion-Bn7COFMk.js +119 -0
- package/dist/src/completion-Bub2N48b.js +118 -0
- package/dist/src/completion-Cf2G9OlM.cjs +123 -0
- package/dist/src/conversationScoring-BiTYJ9MD.js +374 -0
- package/dist/src/conversationScoring-CKL47uIu.js +373 -0
- package/dist/src/conversationScoring-DCvQKp6k.cjs +398 -0
- package/dist/src/conversationScoring-DLNJtDZI.js +373 -0
- package/dist/src/crescendo-5iLk9WiJ.cjs +734 -0
- package/dist/src/crescendo-B5ylG7kW.js +733 -0
- package/dist/src/crescendo-BD7k6TIx.js +730 -0
- package/dist/src/crescendo-DqO2Ch0P.js +732 -0
- package/dist/src/custom-8rv_aG2K.js +617 -0
- package/dist/src/custom-BOtrIHFN.js +619 -0
- package/dist/src/custom-BvN8seCs.cjs +620 -0
- package/dist/src/custom-Cld9v_Y4.js +618 -0
- package/dist/src/dataUrl-BdHUey2l.cjs +3187 -0
- package/dist/src/dataUrl-DBMifX6C.js +3133 -0
- package/dist/src/dataUrl-DUSr-ZvI.js +2868 -0
- package/dist/src/decisions-CLazADTw.js +516 -0
- package/dist/src/decisions-D5X93awq.js +515 -0
- package/dist/src/decisions-DmaeArEn.js +515 -0
- package/dist/src/decisions-DyQJyHJz.cjs +514 -0
- package/dist/src/docker-C9NYQFeu.js +94 -0
- package/dist/src/docker-CGq3mMol.cjs +94 -0
- package/dist/src/docker-DOm7nmpl.js +95 -0
- package/dist/src/docker-skFN-Kfo.js +93 -0
- package/dist/src/embedding-0UbzkTk9.js +82 -0
- package/dist/src/embedding-DTrSDt7k.cjs +86 -0
- package/dist/src/embedding-j2ORNl5H.js +81 -0
- package/dist/src/envoy-BvS8XTQO.js +60 -0
- package/dist/src/envoy-Cn6Hzw0e.js +60 -0
- package/dist/src/envoy-DC3KWcUY.cjs +60 -0
- package/dist/src/envoy-DetHjo5B.js +61 -0
- package/dist/src/eval-Cer9dPe9.js +1920 -0
- package/dist/src/eval-CytYmI2Z.js +2 -0
- package/dist/src/evalResult-DzOq5wt9.js +1300 -0
- package/dist/src/evaluator-BxCmvGtv.js +10578 -0
- package/dist/src/evaluator-Ct7YDELm.js +2 -0
- package/dist/src/evaluatorHelpers-B_AwIrsl.js +600 -0
- package/dist/src/evaluatorHelpers-D1Tpc7gd.js +601 -0
- package/dist/src/evaluatorHelpers-DRR3rLq0.cjs +622 -0
- package/dist/src/fetch-B5KxZuKu.js +1559 -0
- package/dist/src/fetch-BG_Jl7ty.js +1556 -0
- package/dist/src/fetch-BKlgUg08.cjs +1853 -0
- package/dist/src/fetch-C9Fsja0R.js +2 -0
- package/dist/src/fetch-CM7P8KWA.cjs +14 -0
- package/dist/src/fetch-D0FkIB3G.js +9 -0
- package/dist/src/fetch-RXHsZF-J.js +1280 -0
- package/dist/src/fetch-rSECy8jR.js +10 -0
- package/dist/src/functionCallbackUtils-BB9tmf6a.cjs +262 -0
- package/dist/src/functionCallbackUtils-BXk2iY01.js +246 -0
- package/dist/src/functionCallbackUtils-B_cYp7P5.js +245 -0
- package/dist/src/functionCallbackUtils-BfXnPo0o.js +245 -0
- package/dist/src/gemini-image-BXLMADDz.js +471 -0
- package/dist/src/gemini-image-BYUZyEUx.js +472 -0
- package/dist/src/gemini-image-DSt1QubZ.cjs +471 -0
- package/dist/src/gemini-image-DdNDMiZ_.js +471 -0
- package/dist/src/goat-9b-uU_k6.js +514 -0
- package/dist/src/goat-BCJuiDd0.js +515 -0
- package/dist/src/goat-CmAHbemm.js +512 -0
- package/dist/src/goat-DdOTdyoS.cjs +515 -0
- package/dist/src/goblin-Bp5C5lyb.js +22 -0
- package/dist/src/goblin-Dmr7GItI.js +23 -0
- package/dist/src/goblin-DpM8wxlf.cjs +22 -0
- package/dist/src/goblin-cJyH6Pq-.js +22 -0
- package/dist/src/google-B6eaPAbE.js +142 -0
- package/dist/src/google-D-FStdN6.cjs +142 -0
- package/dist/src/google-DAC7BsCW.js +142 -0
- package/dist/src/google-Id18H0Va.js +143 -0
- package/dist/src/graders-BjNQWkaB.js +2 -0
- package/dist/src/graders-CqdIp_vl.js +15470 -0
- package/dist/src/hydra-6Ouh74DE.js +610 -0
- package/dist/src/hydra-BHjhZnLB.cjs +612 -0
- package/dist/src/hydra-BL6k2REV.js +2 -0
- package/dist/src/hydra-BWUc0o67.js +613 -0
- package/dist/src/hydra-CUkEOLKw.js +612 -0
- package/dist/src/image-B6hG_xhb.js +481 -0
- package/dist/src/image-BFaq7Krd.cjs +209 -0
- package/dist/src/image-Bql5C0N9.cjs +504 -0
- package/dist/src/image-BtZfI2pT.js +163 -0
- package/dist/src/image-CIM4oN7Z.cjs +163 -0
- package/dist/src/image-CbAl7Jpu.js +209 -0
- package/dist/src/image-CiYm_yFw.js +209 -0
- package/dist/src/image-DCMNvBiV.js +163 -0
- package/dist/src/image-DL7pIuUZ.js +210 -0
- package/dist/src/image-ey0kxF8o.js +164 -0
- package/dist/src/image-smgIk3rE.js +482 -0
- package/dist/src/index.cjs +27 -27
- package/dist/src/index.d.cts +8 -8
- package/dist/src/index.js +27 -27
- package/dist/src/indirectWebPwn-B_-UpWY5.js +285 -0
- package/dist/src/indirectWebPwn-Cz3SLiEq.js +434 -0
- package/dist/src/indirectWebPwn-D2s8zGiM.cjs +463 -0
- package/dist/src/indirectWebPwn-DXbj2wGu.cjs +285 -0
- package/dist/src/indirectWebPwn-D_4H44E6.js +285 -0
- package/dist/src/indirectWebPwn-L044SrpV.js +434 -0
- package/dist/src/indirectWebPwn-cnmvdavH.js +435 -0
- package/dist/src/indirectWebPwn-zUBzsqTt.js +286 -0
- package/dist/src/interactions-Bu3oVQ-j.js +850 -0
- package/dist/src/interactions-CND010Lh.cjs +850 -0
- package/dist/src/interactions-DAx7tqUz.js +851 -0
- package/dist/src/interactions-DPkIumeh.js +850 -0
- package/dist/src/iterative-BO4JRnpG.js +545 -0
- package/dist/src/iterative-CAK-k9rz.js +548 -0
- package/dist/src/iterative-CDgHc0xO.cjs +549 -0
- package/dist/src/iterative-CXJlHLl9.js +547 -0
- package/dist/src/iterativeImage-BEdGKSmh.cjs +419 -0
- package/dist/src/iterativeImage-BfL0QZw5.js +417 -0
- package/dist/src/iterativeImage-C9KhnibC.js +417 -0
- package/dist/src/iterativeImage-btjkOfWG.js +418 -0
- package/dist/src/iterativeMeta-B5Bdw6QA.js +437 -0
- package/dist/src/iterativeMeta-C3mI4gpT.js +440 -0
- package/dist/src/iterativeMeta-Co2BKyqS.cjs +439 -0
- package/dist/src/iterativeMeta-DD8ihRWD.js +439 -0
- package/dist/src/iterativeTree-AMi4GV2O.js +878 -0
- package/dist/src/iterativeTree-C8FJOEje.cjs +879 -0
- package/dist/src/iterativeTree-CvrY1f2Z.js +877 -0
- package/dist/src/iterativeTree-bPtESmaD.js +876 -0
- package/dist/src/knowledgeBase-Cf5871e3.js +163 -0
- package/dist/src/knowledgeBase-D2PQhqLH.js +164 -0
- package/dist/src/knowledgeBase-DpoMw1IH.cjs +163 -0
- package/dist/src/knowledgeBase-npGFl763.js +163 -0
- package/dist/src/litellm-BBB5DQdt.cjs +146 -0
- package/dist/src/litellm-Bo43ow7r.js +145 -0
- package/dist/src/litellm-CaU8CMLS.js +146 -0
- package/dist/src/litellm-wY7Unh8o.js +147 -0
- package/dist/src/live-5g2w-M-E.js +891 -0
- package/dist/src/live-BfaXsDyD.cjs +891 -0
- package/dist/src/live-C1xewnGD.js +2 -0
- package/dist/src/live-DaF7nYy5.js +892 -0
- package/dist/src/live-lp3urLUw.js +891 -0
- package/dist/src/luma-ray-B7zvKGVG.js +309 -0
- package/dist/src/luma-ray-DCf5fnrz.cjs +309 -0
- package/dist/src/luma-ray-DepBcn6z.js +309 -0
- package/dist/src/luma-ray-XQC4M1pt.js +310 -0
- package/dist/src/main.js +26 -26
- package/dist/src/mantleChat-7xm95vSV.js +154 -0
- package/dist/src/mantleChat-CXhAs5RD.js +155 -0
- package/dist/src/mantleChat-CcE-zjfj.cjs +154 -0
- package/dist/src/mantleChat-Cpefl7Zm.js +154 -0
- package/dist/src/mcp-B0V0ikdM.js +84 -0
- package/dist/src/mcp-CV2k2gwj.js +85 -0
- package/dist/src/memoryPoisoning-BC5FQQWZ.js +111 -0
- package/dist/src/memoryPoisoning-BDwrtZKX.js +111 -0
- package/dist/src/memoryPoisoning-BFemS_FF.js +112 -0
- package/dist/src/memoryPoisoning-DRs2rbVV.cjs +111 -0
- package/dist/src/messages-Bc5oZoAJ.js +1128 -0
- package/dist/src/messages-BkaH8fRW.js +1127 -0
- package/dist/src/messages-CoHlziS5.js +1127 -0
- package/dist/src/messages-Cv_m6kYs.cjs +1161 -0
- package/dist/src/mischievousUser-BcyFxrqJ.js +51 -0
- package/dist/src/mischievousUser-BlhOQSd2.js +52 -0
- package/dist/src/mischievousUser-BuQiKE8D.js +51 -0
- package/dist/src/mischievousUser-ChIOk6cT.cjs +51 -0
- package/dist/src/modelslab-BXIWBTgX.js +171 -0
- package/dist/src/modelslab-ChVsUiaJ.js +170 -0
- package/dist/src/modelslab-DZ6BFlDv.js +170 -0
- package/dist/src/modelslab-DhRr-vyo.cjs +170 -0
- package/dist/src/nova-reel-BL8DrN4_.js +272 -0
- package/dist/src/nova-reel-BiOMUm5q.cjs +272 -0
- package/dist/src/nova-reel-CTsya1hV.js +273 -0
- package/dist/src/nova-reel-kgBY4Svd.js +272 -0
- package/dist/src/nova-sonic-CaSSA3Jq.cjs +374 -0
- package/dist/src/nova-sonic-DLpmoGsR.js +375 -0
- package/dist/src/nova-sonic-DwWc4SoN.js +374 -0
- package/dist/src/nova-sonic-qnReTaXm.js +374 -0
- package/dist/src/novita-B5mAt3Ui.js +114 -0
- package/dist/src/novita-D57vCjDD.js +116 -0
- package/dist/src/novita-ITRtG8IJ.js +115 -0
- package/dist/src/novita-Rh3T13YO.cjs +115 -0
- package/dist/src/nscale-8V7iZ_pI.js +210 -0
- package/dist/src/nscale-BQnMv4pH.cjs +209 -0
- package/dist/src/nscale-BWZXHZVF.js +209 -0
- package/dist/src/nscale-BqrHiUqU.js +207 -0
- package/dist/src/openaiResponses-BMtGTu8R.js +317 -0
- package/dist/src/openaiResponses-CvcI_viE.js +318 -0
- package/dist/src/openaiResponses-DYPZEMX1.cjs +318 -0
- package/dist/src/openaiResponses-DZTg1-kb.js +319 -0
- package/dist/src/openclaw-BeKuig4g.js +1338 -0
- package/dist/src/openclaw-COkdQ83y.js +1337 -0
- package/dist/src/openclaw-CSoX_HQ5.cjs +1344 -0
- package/dist/src/openclaw-DJlhPGCb.js +1336 -0
- package/dist/src/opencode-sdk-BEJftEs6.cjs +1018 -0
- package/dist/src/opencode-sdk-DMvBB3V7.js +1013 -0
- package/dist/src/opencode-sdk-Df7hMjLO.js +1012 -0
- package/dist/src/opencode-sdk-bQp5Xf3W.js +1012 -0
- package/dist/src/openinterpreter-B3GgVZjK.js +431 -0
- package/dist/src/openinterpreter-BiGcU-HN.cjs +435 -0
- package/dist/src/openinterpreter-Buj2l3Eh.js +432 -0
- package/dist/src/openinterpreter-C3_Cg5b_.js +431 -0
- package/dist/src/pricing-0Pampf0q.cjs +999 -0
- package/dist/src/pricing-B8VdhEhY.js +976 -0
- package/dist/src/pricing-CtLA-rKA.js +976 -0
- package/dist/src/promptfoo-4OkHtH9P.cjs +341 -0
- package/dist/src/promptfoo-Bhpm7sH6.js +286 -0
- package/dist/src/promptfoo-BqV8ogVA.js +285 -0
- package/dist/src/promptfoo-S1Q9OHk_.js +286 -0
- package/dist/src/providers-B5zs1ZRv.js +24437 -0
- package/dist/src/providers-Cd6CJh6m.js +2 -0
- package/dist/src/providers-CpJlgHET.js +24039 -0
- package/dist/src/providers-CzvLvK6G.cjs +24180 -0
- package/dist/src/quiverai-1E_IvLHn.js +325 -0
- package/dist/src/quiverai-BXH004Vv.js +325 -0
- package/dist/src/quiverai-Ccya2z8Y.cjs +325 -0
- package/dist/src/quiverai-Cez57oe-.js +326 -0
- package/dist/src/registry-3zX_M9Ik.js +131 -0
- package/dist/src/registry-AuCrKTvS.js +132 -0
- package/dist/src/registry-CxXWKtQG.js +131 -0
- package/dist/src/registry-DG3o66JQ.cjs +131 -0
- package/dist/src/remoteGeneration-CAtvamG6.js +370 -0
- package/dist/src/remoteGeneration-CF225pDl.cjs +482 -0
- package/dist/src/remoteGeneration-DtnqocnL.js +370 -0
- package/dist/src/remoteGeneration-g3KvW-sP.js +371 -0
- package/dist/src/responses-BMbaUXQI.js +1098 -0
- package/dist/src/responses-B_TOSof-.js +1099 -0
- package/dist/src/responses-v-yANwTA.cjs +1109 -0
- package/dist/src/runtimeTransform-BBZv-oUZ.js +156 -0
- package/dist/src/runtimeTransform-DT2v5ovW.js +156 -0
- package/dist/src/runtimeTransform-GXXEIXdS.cjs +161 -0
- package/dist/src/runtimeTransform-JTwBQc-P.js +157 -0
- package/dist/src/sagemaker-B8D0L4rj.cjs +716 -0
- package/dist/src/sagemaker-CR2_AGdB.js +713 -0
- package/dist/src/sagemaker-Cd9qSQUV.js +714 -0
- package/dist/src/sagemaker-mKlltN4p.js +713 -0
- package/dist/src/scanner-PG_8lh8r.js +1971 -0
- package/dist/src/server/index.js +55 -55
- package/dist/src/server-Bmh7sd9F.js +155 -0
- package/dist/src/server-C7b8z6aC.js +63 -0
- package/dist/src/server-CAcovgtL.js +2 -0
- package/dist/src/server-CuuMfKlh.cjs +74 -0
- package/dist/src/server-DMPCj9jy.js +189 -0
- package/dist/src/session-BksXvRH_.cjs +69 -0
- package/dist/src/session-DOxUjqGQ.js +63 -0
- package/dist/src/session-Dujsc-b9.js +62 -0
- package/dist/src/session-VjtIxREd.js +62 -0
- package/dist/src/shared-Bkyz_7e5.cjs +2185 -0
- package/dist/src/shared-DDJg8ycC.js +1929 -0
- package/dist/src/shared-Dh3yfRBd.js +1927 -0
- package/dist/src/shared-tfPT8Tna.js +1928 -0
- package/dist/src/simulatedUser-6JdkyL3k.cjs +252 -0
- package/dist/src/simulatedUser-CFr2mr3M.js +248 -0
- package/dist/src/simulatedUser-DjwwUqx-.js +247 -0
- package/dist/src/slack-C_gIYiUs.js +144 -0
- package/dist/src/slack-DhNbz9CM.cjs +144 -0
- package/dist/src/slack-Dm2iI1zu.js +145 -0
- package/dist/src/strategies-BIY-bNul.js +2248 -0
- package/dist/src/strategies-C1KQQj9G.cjs +2420 -0
- package/dist/src/strategies-DM_3mReG.js +2385 -0
- package/dist/src/telemetry-BhMTibZO.js +2 -0
- package/dist/src/telemetry-C04d25BM.cjs +216 -0
- package/dist/src/telemetry-CIqy4fSC.js +201 -0
- package/dist/src/telemetry-CXozp_6C.js +205 -0
- package/dist/src/telemetry-g7PkBxmY.js +205 -0
- package/dist/src/togetherai-BvCim68-.js +50 -0
- package/dist/src/togetherai-CWyDCA9m.cjs +49 -0
- package/dist/src/togetherai-CeSE31vK.js +49 -0
- package/dist/src/togetherai-_2W0URf8.js +48 -0
- package/dist/src/traceContext-Brw3Oe41.js +1016 -0
- package/dist/src/traceContext-DpAYv27G.js +1015 -0
- package/dist/src/traceContext-KSqhzZI2.cjs +1032 -0
- package/dist/src/transcription-BySopazW.js +175 -0
- package/dist/src/transcription-DO4UPkRI.cjs +178 -0
- package/dist/src/transcription-RJGBa-pC.js +176 -0
- package/dist/src/transcription-fZenF3G5.js +175 -0
- package/dist/src/transform-BzhRc5z2.js +125 -0
- package/dist/src/transform-CPQu05u6.cjs +154 -0
- package/dist/src/transform-DAED8imp.js +126 -0
- package/dist/src/transform-DIOIQDmM.js +125 -0
- package/dist/src/typesafe-ByE0Kxfg.js +253 -0
- package/dist/src/typesafe-CFqGFY34.js +253 -0
- package/dist/src/typesafe-DCWIw-CP.cjs +253 -0
- package/dist/src/typesafe-DyHFV5Qk.js +254 -0
- package/dist/src/util-BHkj9joz.js +2049 -0
- package/dist/src/util-CICwIpmu.cjs +934 -0
- package/dist/src/util-CePiY2xZ.js +286 -0
- package/dist/src/util-CgT3uf4p.js +743 -0
- package/dist/src/util-Cj9drvOY.js +1770 -0
- package/dist/src/util-ClJRjlQA.cjs +357 -0
- package/dist/src/util-Cxf8VF2M.js +395 -0
- package/dist/src/util-D7RdV7rS.js +395 -0
- package/dist/src/util-DMNFhk47.js +351 -0
- package/dist/src/util-DNzh3M0z.js +396 -0
- package/dist/src/util-Df7rfMGb.cjs +2305 -0
- package/dist/src/util-Kf0KnG_6.js +2051 -0
- package/dist/src/util-LEbeiYw_.js +743 -0
- package/dist/src/util-WH8CgVs4.js +352 -0
- package/dist/src/util-cx6Xw8Lw.cjs +478 -0
- package/dist/src/util-qzBqirBH.js +2050 -0
- package/dist/src/vertex-CBAMfRz3.js +854 -0
- package/dist/src/vertex-CMP2IpN9.js +2 -0
- package/dist/src/vertex-CZ5YOotT.js +848 -0
- package/dist/src/vertex-DNsh1F1M.cjs +871 -0
- package/dist/src/vertexLive-BTXYj3-F.js +55 -0
- package/dist/src/vertexLive-Ba_LAqEF.cjs +55 -0
- package/dist/src/vertexLive-DM4sFaaj.js +56 -0
- package/dist/src/vertexLive-JqZOw7HC.js +55 -0
- package/dist/src/video-BY7Q2Gii.cjs +706 -0
- package/dist/src/video-CYElP-CK.js +703 -0
- package/dist/src/video-C_AdEDH0.js +702 -0
- package/dist/src/video-DGvjQ_4j.js +702 -0
- package/package.json +1 -1
- package/dist/src/accounts-Dpb43yde.cjs +0 -276
- package/dist/src/accounts-GKrO1olH.js +0 -229
- package/dist/src/accounts-e4FGOsji.js +0 -227
- package/dist/src/accounts-sUiEJfkB.js +0 -222
- package/dist/src/agentWorkspace-B8A_wuMR.cjs +0 -619
- package/dist/src/agentWorkspace-DSPIscXR.js +0 -593
- package/dist/src/agentWorkspace-DxUqd-XK.js +0 -592
- package/dist/src/agentWorkspace-n0uOJXhD.js +0 -592
- package/dist/src/agentic-utils-9bCj4twQ.js +0 -197
- package/dist/src/agentic-utils-CyCLuLoj.js +0 -197
- package/dist/src/agentic-utils-D23qtOlx.cjs +0 -237
- package/dist/src/agentic-utils-DuBMMNCw.js +0 -198
- package/dist/src/agents-6hDRNoYD.js +0 -777
- package/dist/src/agents-B8w2o7Sc.cjs +0 -777
- package/dist/src/agents-Ck0NXl7v.js +0 -777
- package/dist/src/agents-CwT3B1qB.js +0 -778
- package/dist/src/agents-DOLjfOEq.js +0 -266
- package/dist/src/agents-OcF9hq--.js +0 -267
- package/dist/src/agents-api-CnZZt8bn.cjs +0 -710
- package/dist/src/agents-api-D04u3bmL.js +0 -711
- package/dist/src/agents-api-DWw0_Vio.js +0 -710
- package/dist/src/agents-api-IWHEwp8i.js +0 -710
- package/dist/src/agents-mHt2Mh9O.cjs +0 -266
- package/dist/src/agents-sICccZCA.js +0 -266
- package/dist/src/ai.studio-Ci4rypDT.js +0 -2
- package/dist/src/ai.studio-KkQ6KaHa.js +0 -369
- package/dist/src/ai.studio-gSXK2cGI.js +0 -374
- package/dist/src/ai.studio-nQF_B4DH.cjs +0 -391
- package/dist/src/aimlapi-BeSk5BDV.js +0 -30
- package/dist/src/aimlapi-CzNUhdKu.cjs +0 -29
- package/dist/src/aimlapi-DCkazDPI.js +0 -29
- package/dist/src/aimlapi-WeH5B6K1.js +0 -28
- package/dist/src/anthropicMessages-AcNWTpYO.js +0 -115
- package/dist/src/anthropicMessages-BUtvzbpL.js +0 -114
- package/dist/src/anthropicMessages-DTWhZDCd.js +0 -114
- package/dist/src/anthropicMessages-lGVnSgyx.cjs +0 -114
- package/dist/src/app/assets/index-CyEI5aDN.js +0 -392
- package/dist/src/audio-BE_Duiu1.js +0 -104
- package/dist/src/audio-CiUd00k2.cjs +0 -104
- package/dist/src/audio-Dop6omna.js +0 -105
- package/dist/src/audio-EZNTInr_.js +0 -104
- package/dist/src/authoritativeMarkupInjection-BUqH6hNk.js +0 -78
- package/dist/src/authoritativeMarkupInjection-BmbJdJO0.cjs +0 -78
- package/dist/src/authoritativeMarkupInjection-Cpz12Y3w.js +0 -78
- package/dist/src/authoritativeMarkupInjection-W4XfcH91.js +0 -79
- package/dist/src/aws-B2Jqbnet.js +0 -2433
- package/dist/src/aws-DHtuUIzQ.js +0 -1149
- package/dist/src/aws-DLqXP6wY.js +0 -2433
- package/dist/src/aws-DfduhmwL.cjs +0 -2454
- package/dist/src/base-B9L2Xvpc.js +0 -255
- package/dist/src/base-BTZnIsuH.cjs +0 -305
- package/dist/src/base-BhaWNQPJ.js +0 -462
- package/dist/src/base-Br-G_Xou.js +0 -256
- package/dist/src/base-Bzo8hiUS.cjs +0 -467
- package/dist/src/base-C82fd2jq.js +0 -463
- package/dist/src/base-CRdQwC1W.js +0 -462
- package/dist/src/base-CjGwZNOQ.js +0 -255
- package/dist/src/bedrock-BdMru_ro.js +0 -1300
- package/dist/src/bedrock-CBUmfLX1.cjs +0 -2
- package/dist/src/bedrock-DBDxBaF9.js +0 -2
- package/dist/src/bedrock-DDrECM21.js +0 -1
- package/dist/src/bedrock-DVwkgvRS.js +0 -1
- package/dist/src/bestOfN-AKF5beq4.js +0 -159
- package/dist/src/bestOfN-C1UIVGJV.js +0 -160
- package/dist/src/bestOfN-DlkETbXy.cjs +0 -161
- package/dist/src/bestOfN-XIfEgU-g.js +0 -159
- package/dist/src/cache-BZaVoKaA.js +0 -2
- package/dist/src/cache-CEYhFUsH.js +0 -741
- package/dist/src/cache-Cbw1zH6q.js +0 -782
- package/dist/src/cache-CdaZNb75.js +0 -754
- package/dist/src/cache-DpuIzPxh.cjs +0 -856
- package/dist/src/cerebras-Bpn6FPkJ.js +0 -97
- package/dist/src/cerebras-CqJ0BRCJ.cjs +0 -97
- package/dist/src/cerebras-D4ILa_TY.js +0 -97
- package/dist/src/cerebras-DR8uc7ee.js +0 -98
- package/dist/src/chat-B7PZfaYp.cjs +0 -987
- package/dist/src/chat-BVuSjdEb.js +0 -227
- package/dist/src/chat-BsaZRjXN.js +0 -76
- package/dist/src/chat-C5liqe3Y.js +0 -226
- package/dist/src/chat-C9hyHf5B.js +0 -124
- package/dist/src/chat-CFLalAck.js +0 -226
- package/dist/src/chat-CN8JGrHu.js +0 -76
- package/dist/src/chat-CaHBBpCb.js +0 -123
- package/dist/src/chat-CcbLSghx.js +0 -123
- package/dist/src/chat-CoSN6sr2.js +0 -934
- package/dist/src/chat-CsJRFX8a.cjs +0 -226
- package/dist/src/chat-DFoZLvO_.js +0 -934
- package/dist/src/chat-DiLQvL7r.js +0 -77
- package/dist/src/chat-F6qVSDk3.cjs +0 -123
- package/dist/src/chat-Oq4FaJgI.cjs +0 -76
- package/dist/src/chat-knMfQUKz.js +0 -935
- package/dist/src/claude-agent-sdk-CJkOLpnI.js +0 -999
- package/dist/src/claude-agent-sdk-Ckn76PRD.js +0 -999
- package/dist/src/claude-agent-sdk-DX0gTr11.cjs +0 -1005
- package/dist/src/claude-agent-sdk-LMeikxoR.js +0 -1000
- package/dist/src/client-BFf1r6Z8.js +0 -352
- package/dist/src/client-CdXyDdDi.js +0 -351
- package/dist/src/client-DV8XMu7i.js +0 -351
- package/dist/src/client-iEXtOBKW.cjs +0 -357
- package/dist/src/cloud-B02qcpjf.js +0 -2
- package/dist/src/cloud-BlHP-g1v.cjs +0 -666
- package/dist/src/cloud-C9BI4isF.js +0 -287
- package/dist/src/cloud-CTTLNdvj.js +0 -657
- package/dist/src/cloud-D5X5yQ_d.js +0 -599
- package/dist/src/cloud-QxPkpsHA.js +0 -599
- package/dist/src/cloudflare-ai-DRTRT1fc.js +0 -132
- package/dist/src/cloudflare-ai-DgaXapAV.cjs +0 -133
- package/dist/src/cloudflare-ai-DkuJXijS.js +0 -134
- package/dist/src/cloudflare-ai-wy9QCHku.js +0 -133
- package/dist/src/cloudflare-gateway-9cAN8g29.cjs +0 -276
- package/dist/src/cloudflare-gateway-BVFMD292.js +0 -277
- package/dist/src/cloudflare-gateway-BuUI4p6I.js +0 -276
- package/dist/src/cloudflare-gateway-TlYHizbW.js +0 -276
- package/dist/src/codex-app-server-BPz_feug.cjs +0 -2162
- package/dist/src/codex-app-server-C9noXM9C.js +0 -2155
- package/dist/src/codex-app-server-CEmD-Y5U.js +0 -2
- package/dist/src/codex-app-server-DZolc18r.js +0 -2156
- package/dist/src/codex-app-server-Dd0A37nO.js +0 -2155
- package/dist/src/codex-sdk-BbxjBvBk.cjs +0 -1588
- package/dist/src/codex-sdk-BpXeIs-_.js +0 -1557
- package/dist/src/codex-sdk-BtQp5X0f.js +0 -1552
- package/dist/src/codex-sdk-CH0v9Bk1.js +0 -2
- package/dist/src/codex-sdk-CgrN7JB8.js +0 -1557
- package/dist/src/codex-security-B5fENNUr.js +0 -406
- package/dist/src/codex-security-C6uuJx-y.cjs +0 -411
- package/dist/src/codex-security-CifWtZR_.js +0 -407
- package/dist/src/codex-security-Kg2bOEKy.js +0 -406
- package/dist/src/cometapi-BFpIDLIx.js +0 -55
- package/dist/src/cometapi-C6O2PIrN.js +0 -56
- package/dist/src/cometapi-D5Yupc6F.js +0 -53
- package/dist/src/cometapi-DzgIwJzJ.cjs +0 -55
- package/dist/src/compatible-0jhmVfOp.js +0 -25
- package/dist/src/compatible-DdtwWdJi.cjs +0 -24
- package/dist/src/compatible-Di4nR3sU.js +0 -24
- package/dist/src/compatible-iJKLWdnf.js +0 -24
- package/dist/src/completion-B0_hVUDG.js +0 -119
- package/dist/src/completion-BdI6v0-Q.cjs +0 -123
- package/dist/src/completion-CWcJscwv.js +0 -118
- package/dist/src/conversationScoring-99EOPJRa.js +0 -373
- package/dist/src/conversationScoring-BIq4J0Cq.js +0 -374
- package/dist/src/conversationScoring-DARyeATr.cjs +0 -398
- package/dist/src/conversationScoring-DS48t4Hb.js +0 -373
- package/dist/src/crescendo-CebvXIu4.js +0 -730
- package/dist/src/crescendo-CxrLS0oo.js +0 -732
- package/dist/src/crescendo-DZQXBSkj.js +0 -733
- package/dist/src/crescendo-wjEx68uD.cjs +0 -734
- package/dist/src/custom-BiQ-aUNw.cjs +0 -620
- package/dist/src/custom-ByyB5Z93.js +0 -619
- package/dist/src/custom-C5jOevNb.js +0 -617
- package/dist/src/custom-CCrsCz8o.js +0 -618
- package/dist/src/dataUrl-C9J7wz9H.js +0 -3133
- package/dist/src/dataUrl-CGsBT7UZ.cjs +0 -3187
- package/dist/src/dataUrl-CzKvvWNO.js +0 -2868
- package/dist/src/decisions-BTusXCUx.cjs +0 -514
- package/dist/src/decisions-BYtL9edD.js +0 -515
- package/dist/src/decisions-jYix_gCF.js +0 -515
- package/dist/src/decisions-nxxfHRAN.js +0 -516
- package/dist/src/docker-DDIv4zkg.js +0 -93
- package/dist/src/docker-DVLp_5OG.js +0 -94
- package/dist/src/docker-INm9w0SY.cjs +0 -94
- package/dist/src/docker-sGuoCul_.js +0 -95
- package/dist/src/embedding-CAhqLLrR.js +0 -82
- package/dist/src/embedding-D94GAsti.cjs +0 -86
- package/dist/src/embedding-zb4MAzQy.js +0 -81
- package/dist/src/envoy-BMPszwEa.cjs +0 -60
- package/dist/src/envoy-Bp-s39_8.js +0 -60
- package/dist/src/envoy-BswDt-Ou.js +0 -61
- package/dist/src/envoy-rVbYcV80.js +0 -60
- package/dist/src/eval-B1-XfrC7.js +0 -2
- package/dist/src/eval-pC4qCvLw.js +0 -1920
- package/dist/src/evalResult-CzjCb5bd.js +0 -1300
- package/dist/src/evaluator-CNq2K7J_.js +0 -10578
- package/dist/src/evaluator-LtfxdxEu.js +0 -2
- package/dist/src/evaluatorHelpers-C5J0NYpQ.js +0 -601
- package/dist/src/evaluatorHelpers-DcdCglCs.cjs +0 -622
- package/dist/src/evaluatorHelpers-Rvb88W6B.js +0 -600
- package/dist/src/fetch-5HtnNhHg.js +0 -1556
- package/dist/src/fetch-BCwjoIFd.js +0 -1559
- package/dist/src/fetch-BhfUnKen.js +0 -1280
- package/dist/src/fetch-C08w4vVl.js +0 -9
- package/dist/src/fetch-DBxy8Tlb.cjs +0 -14
- package/dist/src/fetch-DYte6oQX.cjs +0 -1853
- package/dist/src/fetch-ElpfcAVG.js +0 -10
- package/dist/src/fetch-lM1OIaSt.js +0 -2
- package/dist/src/functionCallbackUtils-BCAdWfHO.js +0 -246
- package/dist/src/functionCallbackUtils-BYq9qOhG.js +0 -245
- package/dist/src/functionCallbackUtils-ByWkmVud.cjs +0 -262
- package/dist/src/functionCallbackUtils-D_C_JaFd.js +0 -245
- package/dist/src/gemini-image-CAlwaJhZ.js +0 -471
- package/dist/src/gemini-image-DJoVoOnZ.cjs +0 -471
- package/dist/src/gemini-image-Waio-9Xx.js +0 -472
- package/dist/src/gemini-image-vbY6Ftbf.js +0 -471
- package/dist/src/goat-BWbtyY9c.js +0 -512
- package/dist/src/goat-CXzzeCOQ.cjs +0 -515
- package/dist/src/goat-CfgvzSgZ.js +0 -514
- package/dist/src/goat-DLeoIHBp.js +0 -515
- package/dist/src/goblin-CmfCfwqk.cjs +0 -22
- package/dist/src/goblin-CtcaORRH.js +0 -22
- package/dist/src/goblin-DF6DDhM-.js +0 -22
- package/dist/src/goblin-Nai0xxBV.js +0 -23
- package/dist/src/google-ClpkLtKL.cjs +0 -142
- package/dist/src/google-CrFgKu9k.js +0 -143
- package/dist/src/google-Dj_EIBqS.js +0 -142
- package/dist/src/google-e4-vARv6.js +0 -142
- package/dist/src/graders-BN1IIa71.js +0 -15470
- package/dist/src/graders-C5sCfSP5.js +0 -2
- package/dist/src/hydra-B7RfXVBK.js +0 -2
- package/dist/src/hydra-C1cFN-Jg.js +0 -613
- package/dist/src/hydra-CK6Uc1ia.js +0 -612
- package/dist/src/hydra-Dg65rAP_.js +0 -610
- package/dist/src/hydra-Fqx8l_Xu.cjs +0 -612
- package/dist/src/image-BdlUDAtp.js +0 -163
- package/dist/src/image-C-KwEhwt.cjs +0 -163
- package/dist/src/image-C76fp6NK.cjs +0 -209
- package/dist/src/image-D75ehv3D.js +0 -482
- package/dist/src/image-DKtc5v5W.js +0 -209
- package/dist/src/image-DT_xOkJY.js +0 -163
- package/dist/src/image-DVpdllEE.js +0 -209
- package/dist/src/image-DXZ8AzMf.js +0 -481
- package/dist/src/image-DZl_1mvy.js +0 -164
- package/dist/src/image-DcTD7Ak0.cjs +0 -504
- package/dist/src/image-ndxEvBKB.js +0 -210
- package/dist/src/indirectWebPwn-70WA5x_q.js +0 -435
- package/dist/src/indirectWebPwn-BRVyd3qV.cjs +0 -463
- package/dist/src/indirectWebPwn-BsJVsu0q.js +0 -285
- package/dist/src/indirectWebPwn-Cw6yJu0i.js +0 -285
- package/dist/src/indirectWebPwn-D-PhJzo4.js +0 -286
- package/dist/src/indirectWebPwn-DRPHt2I8.js +0 -434
- package/dist/src/indirectWebPwn-DXtfFhd9.cjs +0 -285
- package/dist/src/indirectWebPwn-DvpNouzc.js +0 -434
- package/dist/src/interactions-5ixfW7Cl.js +0 -850
- package/dist/src/interactions-BOUzfmg1.cjs +0 -850
- package/dist/src/interactions-CSSXcGNc.js +0 -851
- package/dist/src/interactions-WB_sgkN0.js +0 -850
- package/dist/src/iterative-BShRNqjC.cjs +0 -549
- package/dist/src/iterative-BcW_ELtB.js +0 -548
- package/dist/src/iterative-BpHbHz8B.js +0 -547
- package/dist/src/iterative-YcchP12d.js +0 -545
- package/dist/src/iterativeImage-BMFE5Hl7.cjs +0 -419
- package/dist/src/iterativeImage-CkSaYLMY.js +0 -417
- package/dist/src/iterativeImage-DAEUlQX_.js +0 -418
- package/dist/src/iterativeImage-DeUSkEnj.js +0 -417
- package/dist/src/iterativeMeta-DbdaKdEO.cjs +0 -439
- package/dist/src/iterativeMeta-DcF9JWEK.js +0 -437
- package/dist/src/iterativeMeta-DkfPqWIC.js +0 -439
- package/dist/src/iterativeMeta-DkrpnVSs.js +0 -440
- package/dist/src/iterativeTree-CEMY1FhE.cjs +0 -879
- package/dist/src/iterativeTree-Cv5W4tX9.js +0 -877
- package/dist/src/iterativeTree-DGvomd3M.js +0 -876
- package/dist/src/iterativeTree-KbtC2Mkz.js +0 -878
- package/dist/src/knowledgeBase-AYRXn4wO.js +0 -163
- package/dist/src/knowledgeBase-BNqQfx01.js +0 -163
- package/dist/src/knowledgeBase-C0IaCCVs.js +0 -164
- package/dist/src/knowledgeBase-C2uj6wK4.cjs +0 -163
- package/dist/src/litellm-CN1ScAwZ.js +0 -147
- package/dist/src/litellm-CTjwiKSa.js +0 -146
- package/dist/src/litellm-Cd4Nj5ue.js +0 -145
- package/dist/src/litellm-DMqLpEBg.cjs +0 -146
- package/dist/src/live-Bt50-InO.cjs +0 -891
- package/dist/src/live-Bu2ujadG.js +0 -2
- package/dist/src/live-C3M52i3p.js +0 -891
- package/dist/src/live-CRfHMO3B.js +0 -892
- package/dist/src/live-iCIpO14m.js +0 -891
- package/dist/src/luma-ray-B8eHC4c8.cjs +0 -309
- package/dist/src/luma-ray-BIvkPw0s.js +0 -309
- package/dist/src/luma-ray-ChsiBxMA.js +0 -309
- package/dist/src/luma-ray-DAvKrInz.js +0 -310
- package/dist/src/mantleChat-5YeEXAZI.js +0 -154
- package/dist/src/mantleChat-D--mW3hl.js +0 -154
- package/dist/src/mantleChat-DHP3siNg.cjs +0 -154
- package/dist/src/mantleChat-wBfAX46o.js +0 -155
- package/dist/src/mcp-49jlEcTQ.js +0 -85
- package/dist/src/mcp-__PIz81I.js +0 -84
- package/dist/src/memoryPoisoning-Chxge74M.js +0 -111
- package/dist/src/memoryPoisoning-QH6NCUVE.js +0 -112
- package/dist/src/memoryPoisoning-tCxZt8Nz.js +0 -111
- package/dist/src/memoryPoisoning-ymrRItRR.cjs +0 -111
- package/dist/src/messages-BE_eZ7NA.js +0 -1127
- package/dist/src/messages-Bo638ShI.js +0 -1127
- package/dist/src/messages-BzR0-NQ1.js +0 -1128
- package/dist/src/messages-Cbg5Pfd0.cjs +0 -1161
- package/dist/src/mischievousUser-BtED2Z5Z.cjs +0 -51
- package/dist/src/mischievousUser-KqSOjrDJ.js +0 -51
- package/dist/src/mischievousUser-YMD41YNZ.js +0 -51
- package/dist/src/mischievousUser-zBxlNdCu.js +0 -52
- package/dist/src/modelslab-B8gZxtfE.js +0 -171
- package/dist/src/modelslab-C7bmVpTB.js +0 -170
- package/dist/src/modelslab-CCeQCTZg.js +0 -170
- package/dist/src/modelslab-CvBJGv7y.cjs +0 -170
- package/dist/src/nova-reel-BOEWsEKA.cjs +0 -272
- package/dist/src/nova-reel-BtyBXq5M.js +0 -273
- package/dist/src/nova-reel-C1eF3-EE.js +0 -272
- package/dist/src/nova-reel-YhgrxEKT.js +0 -272
- package/dist/src/nova-sonic-BaERP20w.js +0 -374
- package/dist/src/nova-sonic-CxgM3O-P.cjs +0 -374
- package/dist/src/nova-sonic-DJS22fC3.js +0 -375
- package/dist/src/nova-sonic-DwvwHyRX.js +0 -374
- package/dist/src/novita-D1l2tG0O.js +0 -116
- package/dist/src/novita-D84VM3v0.cjs +0 -115
- package/dist/src/novita-DGInvwfR.js +0 -115
- package/dist/src/novita-vXHkXhTg.js +0 -114
- package/dist/src/nscale-CU0Ldr00.js +0 -209
- package/dist/src/nscale-ClfKlQeM.cjs +0 -209
- package/dist/src/nscale-DxaVnF0x.js +0 -210
- package/dist/src/nscale-_poVxIrO.js +0 -207
- package/dist/src/openaiResponses-CJGsneNj.js +0 -317
- package/dist/src/openaiResponses-CKSl5Sdg.js +0 -319
- package/dist/src/openaiResponses-DC8rzFUc.js +0 -318
- package/dist/src/openaiResponses-rMHIA3dV.cjs +0 -318
- package/dist/src/openclaw-CCbvsNFW.cjs +0 -1344
- package/dist/src/openclaw-CZw1lCDZ.js +0 -1336
- package/dist/src/openclaw-ChFLgC-a.js +0 -1338
- package/dist/src/openclaw-DrPMoRrH.js +0 -1337
- package/dist/src/opencode-sdk-2EfIDhFp.cjs +0 -1018
- package/dist/src/opencode-sdk-CHw3F845.js +0 -1013
- package/dist/src/opencode-sdk-D0EGGxvy.js +0 -1012
- package/dist/src/opencode-sdk-jSS7NI2Q.js +0 -1012
- package/dist/src/openinterpreter-CY622xHC.js +0 -431
- package/dist/src/openinterpreter-DATyhuhP.js +0 -432
- package/dist/src/openinterpreter-DDUMyIf1.js +0 -431
- package/dist/src/openinterpreter-s5Tz6Lid.cjs +0 -435
- package/dist/src/pricing-C498twd2.js +0 -976
- package/dist/src/pricing-DBd_bMIh.cjs +0 -999
- package/dist/src/pricing-ISrMCskv.js +0 -976
- package/dist/src/promptfoo-6p0WG2ih.js +0 -286
- package/dist/src/promptfoo-BQRfgNs_.js +0 -285
- package/dist/src/promptfoo-Bqo88z20.cjs +0 -341
- package/dist/src/promptfoo-Cq5AVI3I.js +0 -286
- package/dist/src/providers-ATbeMX5E.cjs +0 -24180
- package/dist/src/providers-B7F1FiNI.js +0 -2
- package/dist/src/providers-DazIw8mI.js +0 -24039
- package/dist/src/providers-QvGlNAD0.js +0 -24437
- package/dist/src/quiverai-BPlNcLkV.cjs +0 -325
- package/dist/src/quiverai-By99-YmJ.js +0 -325
- package/dist/src/quiverai-CmmByDqo.js +0 -325
- package/dist/src/quiverai-HZkoJJqw.js +0 -326
- package/dist/src/registry-BLTnTfjT.cjs +0 -131
- package/dist/src/registry-BMC-COHT.js +0 -132
- package/dist/src/registry-C8UZtmBp.js +0 -131
- package/dist/src/registry-CfwEUYXG.js +0 -131
- package/dist/src/remoteGeneration-Bgg6kC5V.js +0 -370
- package/dist/src/remoteGeneration-CKJFE960.cjs +0 -482
- package/dist/src/remoteGeneration-DaxwJDKv.js +0 -370
- package/dist/src/remoteGeneration-vHMGVKr1.js +0 -371
- package/dist/src/responses-BvnyIHrq.js +0 -1099
- package/dist/src/responses-CERAgvf-.js +0 -1098
- package/dist/src/responses-CwgjeuOg.cjs +0 -1109
- package/dist/src/runtimeTransform-3RF9Avyg.cjs +0 -161
- package/dist/src/runtimeTransform-C51Z5j4H.js +0 -156
- package/dist/src/runtimeTransform-CKE_Iyv8.js +0 -157
- package/dist/src/runtimeTransform-Cs11xJpj.js +0 -156
- package/dist/src/sagemaker-BJ4dOCxE.js +0 -713
- package/dist/src/sagemaker-Bt3JUAWq.js +0 -714
- package/dist/src/sagemaker-QVKyLgLF.cjs +0 -716
- package/dist/src/sagemaker-l3IB8iTs.js +0 -713
- package/dist/src/scanner-DGjIiTZ1.js +0 -1971
- package/dist/src/server-BNaLZH6u.js +0 -63
- package/dist/src/server-CBMuQul3.js +0 -189
- package/dist/src/server-CMKKIzKv.cjs +0 -74
- package/dist/src/server-CN2IS9Cs.js +0 -155
- package/dist/src/server-ua4cqbjC.js +0 -2
- package/dist/src/session-CQIjq_HZ.cjs +0 -69
- package/dist/src/session-FTlg8sEu.js +0 -62
- package/dist/src/session-GBQXtPWp.js +0 -63
- package/dist/src/session-_0-rTdwY.js +0 -62
- package/dist/src/shared-BtuO-OAM.js +0 -1927
- package/dist/src/shared-Ci78wTZX.js +0 -1928
- package/dist/src/shared-Dd3rimdM.js +0 -1929
- package/dist/src/shared-KAjFxRre.cjs +0 -2185
- package/dist/src/simulatedUser--OjW6xCx.js +0 -247
- package/dist/src/simulatedUser-D0-slRye.cjs +0 -252
- package/dist/src/simulatedUser-D1Kh_cwA.js +0 -248
- package/dist/src/slack-BX0FUevO.js +0 -144
- package/dist/src/slack-CcwXFiJE.cjs +0 -144
- package/dist/src/slack-CnfqKfXp.js +0 -145
- package/dist/src/strategies-2ntcK4tN.js +0 -2248
- package/dist/src/strategies-DZIW7Zcs.js +0 -2385
- package/dist/src/strategies-YRDF2j-N.cjs +0 -2420
- package/dist/src/telemetry-CL8CVA4p.js +0 -205
- package/dist/src/telemetry-Cix90qqz.js +0 -201
- package/dist/src/telemetry-CkmlqTjV.js +0 -205
- package/dist/src/telemetry-DQH7l5bb.js +0 -2
- package/dist/src/telemetry-DUCXc1-r.cjs +0 -216
- package/dist/src/togetherai-3yUt5Ck7.js +0 -49
- package/dist/src/togetherai-BJUByLwt.cjs +0 -49
- package/dist/src/togetherai-Bh6KZkmd.js +0 -50
- package/dist/src/togetherai-DDl9yk3b.js +0 -48
- package/dist/src/traceContext-BiJVppjT.cjs +0 -1032
- package/dist/src/traceContext-CKKluULP.js +0 -1016
- package/dist/src/traceContext-D3Sk8fO-.js +0 -1015
- package/dist/src/transcription-BoVQKIVz.js +0 -175
- package/dist/src/transcription-Bs5u8780.js +0 -175
- package/dist/src/transcription-Dl654d1p.cjs +0 -178
- package/dist/src/transcription-VEvhM1Fu.js +0 -176
- package/dist/src/transform-BAbkGpvl.js +0 -125
- package/dist/src/transform-C_j4hUH8.js +0 -126
- package/dist/src/transform-Da86hs4M.cjs +0 -154
- package/dist/src/transform-_i1raQNo.js +0 -125
- package/dist/src/typesafe-CKXBeh82.cjs +0 -253
- package/dist/src/typesafe-D3VaGeNm.js +0 -253
- package/dist/src/typesafe-DYM-SFNH.js +0 -253
- package/dist/src/typesafe-LXmSbw8F.js +0 -254
- package/dist/src/util-41rb0XHX.js +0 -743
- package/dist/src/util-B0WlHYFM.js +0 -2049
- package/dist/src/util-BD1R_PsR.js +0 -1770
- package/dist/src/util-BLbM_ItC.js +0 -395
- package/dist/src/util-C72P0iIa.js +0 -352
- package/dist/src/util-C7MpGlJ6.cjs +0 -2305
- package/dist/src/util-CCtqagKc.js +0 -286
- package/dist/src/util-CM2Ec_uY.js +0 -2051
- package/dist/src/util-CSSAWO8v.js +0 -351
- package/dist/src/util-CkQc-fx3.cjs +0 -934
- package/dist/src/util-DcOlFTFa.cjs +0 -478
- package/dist/src/util-DluGTGVB.js +0 -395
- package/dist/src/util-PfQ60chz.js +0 -743
- package/dist/src/util-f14-CPij.js +0 -396
- package/dist/src/util-l9pXX3Eu.cjs +0 -357
- package/dist/src/util-o_BnlYqS.js +0 -2050
- package/dist/src/vertex-B_-gQgzc.js +0 -2
- package/dist/src/vertex-CU4gqoYa.js +0 -854
- package/dist/src/vertex-DZ42UHb3.js +0 -848
- package/dist/src/vertex-DsYQJA0T.cjs +0 -871
- package/dist/src/vertexLive-BvIaHKGB.js +0 -55
- package/dist/src/vertexLive-CTULqNx7.js +0 -56
- package/dist/src/vertexLive-DjJ_YQBe.cjs +0 -55
- package/dist/src/vertexLive-STUGcteB.js +0 -55
- package/dist/src/video-CAQGmtEV.js +0 -703
- package/dist/src/video-_FSTWlwX.js +0 -702
- package/dist/src/video-aBPJPWdt.js +0 -702
- package/dist/src/video-gDjkWv5m.cjs +0 -706
|
@@ -0,0 +1,1920 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { S as sanitizeConfigForOutput, T as sanitizeTracingConfigForPersistence, c as logger, w as sanitizeRuntimeOptions } from "./logger-pCNnmVuz.js";
|
|
3
|
+
import { A as hashPrompt, F as HUMAN_ASSERTION_TYPE, _ as getCachedResultsCount, a as getStripFlags, c as projectPrompt, d as stripTraceLinkageFromMetadata, g as notifyEvaluationsDeleted, h as notifyEvaluationChanged, i as getResultIndexKey, l as projectTracesForOutput, n as PROMPTFOO_METADATA_KEY, o as persistRepeatMetadata, p as invalidateEvaluationCache, s as persistTraceMetadata, t as EvalResult, v as getTotalResultRowCount, y as queryTestIndicesOptimized } from "./evalResult-DzOq5wt9.js";
|
|
4
|
+
import { N as isNonTransientHttpStatus, w as NON_TRANSIENT_HTTP_STATUSES } from "./fetch-RXHsZF-J.js";
|
|
5
|
+
import { t as invariant } from "./invariant-CbHB1xyx.js";
|
|
6
|
+
import { a as getAuthor } from "./accounts-BOxNYxVN.js";
|
|
7
|
+
import { t as getCurrentTimestamp } from "./time-Ct6CnABs.js";
|
|
8
|
+
import { O as ResultFailureReason, St as PLUGIN_CATEGORIES, a as evalResultsTable, c as evalsToPromptsTable, d as promptsTable, f as spansTable, g as getDb, i as datasetsTable, l as evalsToTagsTable, m as tracesTable, nt as riskCategorySeverityMap, o as evalsTable, p as tagsTable, s as evalsToDatasetsTable } from "./tables-BONxKPrt.js";
|
|
9
|
+
import { n as sha256, t as randomSequence } from "./createHash-DqA6GWxE.js";
|
|
10
|
+
import { n as getTraceStore } from "./store-DFoDZ_D2.js";
|
|
11
|
+
import { c as accumulateTokenUsage, d as createEmptyTokenUsage, r as accumulateGenerationTokenUsage } from "./tokenUsageUtils-CHs91tUW.js";
|
|
12
|
+
import { t as getActualPrompt } from "./providerResponse-ChVTuVd0.js";
|
|
13
|
+
import { and, desc, eq, inArray, sql } from "drizzle-orm";
|
|
14
|
+
//#region src/database/evalDeletion.ts
|
|
15
|
+
const SQLITE_MAX_BOUND_PARAMETERS = 999;
|
|
16
|
+
/**
|
|
17
|
+
* Removes spans and traces tied to the given eval ids.
|
|
18
|
+
*
|
|
19
|
+
* `traces.evaluation_id -> evals.id` and `spans.trace_id -> traces.trace_id` are
|
|
20
|
+
* FK-enforced (see `pragma foreign_keys = ON`) without `ON DELETE CASCADE`, so any
|
|
21
|
+
* eval-deletion path must clear spans before traces before the eval row itself.
|
|
22
|
+
*
|
|
23
|
+
* Spans are removed via a correlated subquery so the query stays within SQLite's
|
|
24
|
+
* bound-parameter limit even when an eval has many traces.
|
|
25
|
+
*/
|
|
26
|
+
async function deleteTraceRecordsForEvals(db, evalIds) {
|
|
27
|
+
for (let i = 0; i < evalIds.length; i += SQLITE_MAX_BOUND_PARAMETERS) {
|
|
28
|
+
const evalIdBatch = evalIds.slice(i, i + SQLITE_MAX_BOUND_PARAMETERS);
|
|
29
|
+
await db.delete(spansTable).where(sql`${spansTable.traceId} in (
|
|
30
|
+
select ${tracesTable.traceId}
|
|
31
|
+
from ${tracesTable}
|
|
32
|
+
where ${inArray(tracesTable.evaluationId, evalIdBatch)}
|
|
33
|
+
)`).run();
|
|
34
|
+
await db.delete(tracesTable).where(inArray(tracesTable.evaluationId, evalIdBatch)).run();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/presentation/redteamMetrics.ts
|
|
39
|
+
/** Percentage of tests that failed grading; zero when there are no tests. */
|
|
40
|
+
function calculateAttackSuccessRate(testCount, failCount) {
|
|
41
|
+
return testCount > 0 ? failCount / testCount * 100 : 0;
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/presentation/redteamConfig.ts
|
|
45
|
+
function getRiskCategorySeverityMap(plugins) {
|
|
46
|
+
const overrides = plugins?.reduce((acc, plugin) => {
|
|
47
|
+
if (plugin.severity) {
|
|
48
|
+
acc[plugin.id] = plugin.severity;
|
|
49
|
+
const policyId = plugin.config?.policy?.id;
|
|
50
|
+
if (plugin.id === "policy" && policyId) acc[policyId] = plugin.severity;
|
|
51
|
+
}
|
|
52
|
+
return acc;
|
|
53
|
+
}, {}) || {};
|
|
54
|
+
return {
|
|
55
|
+
...riskCategorySeverityMap,
|
|
56
|
+
...overrides
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/util/calculateFilteredMetrics.ts
|
|
61
|
+
/**
|
|
62
|
+
* Calculate metrics for filtered evaluation results.
|
|
63
|
+
*
|
|
64
|
+
* This module implements optimized SQL aggregation to calculate metrics for
|
|
65
|
+
* filtered evaluation datasets. It uses a single GROUP BY query to aggregate
|
|
66
|
+
* ALL prompts at once, achieving significant performance improvements over
|
|
67
|
+
* the naive approach of querying each prompt separately.
|
|
68
|
+
*
|
|
69
|
+
* SECURITY: This module uses Drizzle's sql template strings for parameterized queries
|
|
70
|
+
* to prevent SQL injection. The whereSql parameter is a SQL fragment, not a string,
|
|
71
|
+
* ensuring all user-provided values are properly escaped.
|
|
72
|
+
*
|
|
73
|
+
* Performance targets:
|
|
74
|
+
* - Simple eval (2 prompts, 100 results): <50ms
|
|
75
|
+
* - Complex eval (10 prompts, 1000 results): <150ms
|
|
76
|
+
* - Large eval (10 prompts, 10000 results): <500ms
|
|
77
|
+
*
|
|
78
|
+
* Critical design decisions:
|
|
79
|
+
* 1. Single GROUP BY query for all basic metrics + token usage
|
|
80
|
+
* 2. SQL JSON aggregation for named scores (avoids memory issues)
|
|
81
|
+
* 3. SQL JSON aggregation for assertions (complex nested JSON)
|
|
82
|
+
* 4. OOM protection with MAX_RESULTS_FOR_METRICS limit
|
|
83
|
+
*/
|
|
84
|
+
/**
|
|
85
|
+
* Maximum number of results to process for metrics calculation.
|
|
86
|
+
* Protects against OOM on extremely large filtered datasets.
|
|
87
|
+
*/
|
|
88
|
+
const MAX_RESULTS_FOR_METRICS = 5e4;
|
|
89
|
+
function jsonUsageNumber(column, usagePath, field) {
|
|
90
|
+
return sql`COALESCE(CAST(json_extract(${column}, ${`${usagePath}.${field}`}) AS INTEGER), 0)`;
|
|
91
|
+
}
|
|
92
|
+
function jsonUsageTotal(column, usagePath, cachedResponsePath) {
|
|
93
|
+
const explicitTotal = sql`CAST(json_extract(${column}, ${`${usagePath}.total`}) AS INTEGER)`;
|
|
94
|
+
const prompt = jsonUsageNumber(column, usagePath, "prompt");
|
|
95
|
+
const completion = jsonUsageNumber(column, usagePath, "completion");
|
|
96
|
+
const cached = jsonUsageNumber(column, usagePath, "cached");
|
|
97
|
+
const requests = sql`CAST(json_extract(${column}, ${`${usagePath}.numRequests`}) AS INTEGER)`;
|
|
98
|
+
const explicitlyCached = cachedResponsePath ? sql`COALESCE(json_extract(${column}, ${cachedResponsePath}), 0) = 1` : sql`0`;
|
|
99
|
+
return sql`CASE
|
|
100
|
+
WHEN ${explicitlyCached} THEN
|
|
101
|
+
CASE
|
|
102
|
+
WHEN COALESCE(${explicitTotal}, 0) > 0 THEN ${explicitTotal}
|
|
103
|
+
WHEN ${cached} > 0 THEN ${cached}
|
|
104
|
+
ELSE ${prompt} + ${completion}
|
|
105
|
+
END
|
|
106
|
+
WHEN ${explicitTotal} IS NOT NULL THEN ${explicitTotal}
|
|
107
|
+
WHEN ${requests} = 0 AND ${cached} > 0 AND (${prompt} + ${completion}) <= ${cached} THEN 0
|
|
108
|
+
ELSE ${prompt} + ${completion}
|
|
109
|
+
END`;
|
|
110
|
+
}
|
|
111
|
+
function jsonUsageRequests(column, usagePath, cachedResponsePath) {
|
|
112
|
+
const explicitlyCached = cachedResponsePath ? sql`COALESCE(json_extract(${column}, ${cachedResponsePath}), 0) = 1` : sql`0`;
|
|
113
|
+
return sql`CASE
|
|
114
|
+
WHEN json_extract(${column}, ${usagePath}) IS NULL THEN 0
|
|
115
|
+
WHEN ${explicitlyCached} THEN
|
|
116
|
+
MAX(COALESCE(CAST(json_extract(${column}, ${`${usagePath}.numRequests`}) AS INTEGER), 1), 1)
|
|
117
|
+
ELSE COALESCE(CAST(json_extract(${column}, ${`${usagePath}.numRequests`}) AS INTEGER), 1)
|
|
118
|
+
END`;
|
|
119
|
+
}
|
|
120
|
+
function jsonUsageCached(column, usagePath, cachedResponsePath) {
|
|
121
|
+
const cached = jsonUsageNumber(column, usagePath, "cached");
|
|
122
|
+
if (!cachedResponsePath) return cached;
|
|
123
|
+
const reportedTotal = sql`COALESCE(
|
|
124
|
+
CAST(json_extract(${column}, ${`${usagePath}.total`}) AS INTEGER),
|
|
125
|
+
${jsonUsageNumber(column, usagePath, "prompt")} + ${jsonUsageNumber(column, usagePath, "completion")}
|
|
126
|
+
)`;
|
|
127
|
+
return sql`CASE
|
|
128
|
+
WHEN COALESCE(json_extract(${column}, ${cachedResponsePath}), 0) = 1 THEN
|
|
129
|
+
CASE WHEN ${cached} > 0 THEN ${cached} ELSE ${reportedTotal} END
|
|
130
|
+
ELSE ${cached}
|
|
131
|
+
END`;
|
|
132
|
+
}
|
|
133
|
+
function jsonUsageField(column, usagePath, field, cachedResponsePath) {
|
|
134
|
+
switch (field) {
|
|
135
|
+
case "total": return jsonUsageTotal(column, usagePath, cachedResponsePath);
|
|
136
|
+
case "numRequests": return jsonUsageRequests(column, usagePath, cachedResponsePath);
|
|
137
|
+
case "cached": return jsonUsageCached(column, usagePath, cachedResponsePath);
|
|
138
|
+
default: return jsonUsageNumber(column, usagePath, field);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function jsonIncurredUsageField(column, logicalPath, incurredPath, field, options) {
|
|
142
|
+
const logicalUsage = jsonUsageField(column, logicalPath, field, options?.cachedResponsePath);
|
|
143
|
+
const incurredUsage = jsonUsageField(column, incurredPath, field);
|
|
144
|
+
const parentHasIncurredUsage = options?.parentIncurredPath ? sql`json_extract(${column}, ${options.parentIncurredPath}) IS NOT NULL` : sql`0`;
|
|
145
|
+
const explicitlyCached = options?.cachedResponsePath ? sql`COALESCE(json_extract(${column}, ${options.cachedResponsePath}), 0) = 1` : sql`0`;
|
|
146
|
+
return sql`CASE
|
|
147
|
+
WHEN json_extract(${column}, ${incurredPath}) IS NOT NULL THEN ${incurredUsage}
|
|
148
|
+
WHEN ${parentHasIncurredUsage} OR ${explicitlyCached} THEN 0
|
|
149
|
+
ELSE ${logicalUsage}
|
|
150
|
+
END`;
|
|
151
|
+
}
|
|
152
|
+
function getTokenUsageCounts(row, prefix) {
|
|
153
|
+
return {
|
|
154
|
+
total: row[`${prefix}total_tokens`] || 0,
|
|
155
|
+
prompt: row[`${prefix}prompt_tokens`] || 0,
|
|
156
|
+
completion: row[`${prefix}completion_tokens`] || 0,
|
|
157
|
+
cached: row[`${prefix}cached_tokens`] || 0,
|
|
158
|
+
numRequests: (prefix ? row[`${prefix}num_requests`] : row.num_requests_with_tokens) || 0
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function getFilteredTokenUsage(row) {
|
|
162
|
+
return {
|
|
163
|
+
...getTokenUsageCounts(row, ""),
|
|
164
|
+
attacker: getTokenUsageCounts(row, "attacker_"),
|
|
165
|
+
assertions: getTokenUsageCounts(row, "grading_"),
|
|
166
|
+
...row.has_incurred_usage > 0 && { incurredTokenUsage: {
|
|
167
|
+
...getTokenUsageCounts(row, "incurred_"),
|
|
168
|
+
attacker: getTokenUsageCounts(row, "incurred_attacker_"),
|
|
169
|
+
assertions: getTokenUsageCounts(row, "incurred_grading_")
|
|
170
|
+
} }
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Aggregate filtered rows across all prompts. The count limit bounds the query;
|
|
175
|
+
* three grouped queries collect row metrics, named scores, and assertion counts.
|
|
176
|
+
*/
|
|
177
|
+
async function calculateFilteredMetrics(opts) {
|
|
178
|
+
const { numPrompts, whereSql } = opts;
|
|
179
|
+
try {
|
|
180
|
+
const countResult = await getResultCount(whereSql);
|
|
181
|
+
if (countResult > MAX_RESULTS_FOR_METRICS) {
|
|
182
|
+
logger.warn(`Filtered result count ${countResult} exceeds limit ${MAX_RESULTS_FOR_METRICS}`, { evalId: opts.evalId });
|
|
183
|
+
throw new Error(`Result count ${countResult} exceeds maximum ${MAX_RESULTS_FOR_METRICS}`);
|
|
184
|
+
}
|
|
185
|
+
return await calculateWithOptimizedQuery(opts);
|
|
186
|
+
} catch (error) {
|
|
187
|
+
logger.error("Failed to calculate filtered metrics", { error });
|
|
188
|
+
return createEmptyMetricsArray(numPrompts);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get count of filtered results (for OOM protection)
|
|
193
|
+
*
|
|
194
|
+
* SECURITY: Uses parameterized SQL query via Drizzle's sql template strings.
|
|
195
|
+
*/
|
|
196
|
+
async function getResultCount(whereSql) {
|
|
197
|
+
const db = await getDb();
|
|
198
|
+
const query = sql`
|
|
199
|
+
SELECT COUNT(*) as count
|
|
200
|
+
FROM eval_results
|
|
201
|
+
WHERE ${whereSql}
|
|
202
|
+
`;
|
|
203
|
+
return (await db.get(query))?.count || 0;
|
|
204
|
+
}
|
|
205
|
+
/** Aggregate all prompts together using parameterized SQL. */
|
|
206
|
+
async function calculateWithOptimizedQuery(opts) {
|
|
207
|
+
const { numPrompts, whereSql } = opts;
|
|
208
|
+
const db = await getDb();
|
|
209
|
+
const metrics = createEmptyMetricsArray(numPrompts);
|
|
210
|
+
const response = sql`response`;
|
|
211
|
+
const gradingResult = sql`grading_result`;
|
|
212
|
+
const targetPath = "$.tokenUsage";
|
|
213
|
+
const incurredTargetPath = "$.tokenUsage.incurredTokenUsage";
|
|
214
|
+
const attackerPath = "$.tokenUsage.attacker";
|
|
215
|
+
const incurredAttackerPath = "$.tokenUsage.incurredTokenUsage.attacker";
|
|
216
|
+
const internalGradingPath = "$.tokenUsage.assertions";
|
|
217
|
+
const incurredInternalGradingPath = "$.tokenUsage.incurredTokenUsage.assertions";
|
|
218
|
+
const gradingPath = "$.tokensUsed";
|
|
219
|
+
const incurredGradingPath = "$.tokensUsed.incurredTokenUsage";
|
|
220
|
+
const gradingCachePath = "$.metadata.cachedResponse";
|
|
221
|
+
const responseCachePath = "$.cached";
|
|
222
|
+
const incurredTargetUsage = (field) => jsonIncurredUsageField(response, targetPath, incurredTargetPath, field, { cachedResponsePath: responseCachePath });
|
|
223
|
+
const incurredAttackerUsage = (field) => jsonIncurredUsageField(response, attackerPath, incurredAttackerPath, field, {
|
|
224
|
+
cachedResponsePath: responseCachePath,
|
|
225
|
+
parentIncurredPath: incurredTargetPath
|
|
226
|
+
});
|
|
227
|
+
const incurredInternalGradingUsage = (field) => jsonIncurredUsageField(response, internalGradingPath, incurredInternalGradingPath, field, {
|
|
228
|
+
cachedResponsePath: responseCachePath,
|
|
229
|
+
parentIncurredPath: incurredTargetPath
|
|
230
|
+
});
|
|
231
|
+
const incurredGradingUsage = (field) => jsonIncurredUsageField(gradingResult, gradingPath, incurredGradingPath, field, { cachedResponsePath: gradingCachePath });
|
|
232
|
+
const basicMetricsQuery = sql`
|
|
233
|
+
SELECT
|
|
234
|
+
prompt_idx,
|
|
235
|
+
SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) as pass_count,
|
|
236
|
+
SUM(CASE WHEN success = 0 AND failure_reason != ${ResultFailureReason.ERROR} THEN 1 ELSE 0 END) as fail_count,
|
|
237
|
+
SUM(CASE WHEN failure_reason = ${ResultFailureReason.ERROR} THEN 1 ELSE 0 END) as error_count,
|
|
238
|
+
SUM(CASE WHEN json_extract(${response}, ${responseCachePath}) = 1 THEN 1 ELSE 0 END) as cache_hit_count,
|
|
239
|
+
SUM(score) as total_score,
|
|
240
|
+
SUM(latency_ms) as total_latency,
|
|
241
|
+
SUM(cost) as total_cost,
|
|
242
|
+
SUM(CASE WHEN json_extract(response, '$.incurredCost') IS NOT NULL
|
|
243
|
+
OR json_extract(response, '$.cached') = 1 THEN 1 ELSE 0 END) as has_incurred_cost,
|
|
244
|
+
SUM(COALESCE(json_extract(response, '$.incurredCost'),
|
|
245
|
+
CASE WHEN json_extract(response, '$.cached') = 1 THEN 0 ELSE cost END, 0)) as incurred_cost,
|
|
246
|
+
-- Token usage aggregation (token usage is inside response JSON)
|
|
247
|
+
SUM(${jsonUsageTotal(response, targetPath)}) as total_tokens,
|
|
248
|
+
SUM(${jsonUsageNumber(response, targetPath, "prompt")}) as prompt_tokens,
|
|
249
|
+
SUM(${jsonUsageNumber(response, targetPath, "completion")}) as completion_tokens,
|
|
250
|
+
SUM(${jsonUsageCached(response, targetPath)}) as cached_tokens,
|
|
251
|
+
SUM(${jsonUsageRequests(response, targetPath)}) as num_requests_with_tokens,
|
|
252
|
+
SUM(${jsonUsageTotal(response, attackerPath)}) as attacker_total_tokens,
|
|
253
|
+
SUM(${jsonUsageNumber(response, attackerPath, "prompt")}) as attacker_prompt_tokens,
|
|
254
|
+
SUM(${jsonUsageNumber(response, attackerPath, "completion")}) as attacker_completion_tokens,
|
|
255
|
+
SUM(${jsonUsageCached(response, attackerPath)}) as attacker_cached_tokens,
|
|
256
|
+
SUM(${jsonUsageRequests(response, attackerPath)}) as attacker_num_requests,
|
|
257
|
+
SUM(
|
|
258
|
+
${jsonUsageTotal(response, internalGradingPath)} +
|
|
259
|
+
${jsonUsageTotal(gradingResult, gradingPath, gradingCachePath)}
|
|
260
|
+
) as grading_total_tokens,
|
|
261
|
+
SUM(
|
|
262
|
+
${jsonUsageNumber(response, internalGradingPath, "prompt")} +
|
|
263
|
+
${jsonUsageNumber(gradingResult, gradingPath, "prompt")}
|
|
264
|
+
) as grading_prompt_tokens,
|
|
265
|
+
SUM(
|
|
266
|
+
${jsonUsageNumber(response, internalGradingPath, "completion")} +
|
|
267
|
+
${jsonUsageNumber(gradingResult, gradingPath, "completion")}
|
|
268
|
+
) as grading_completion_tokens,
|
|
269
|
+
SUM(
|
|
270
|
+
${jsonUsageCached(response, internalGradingPath)} +
|
|
271
|
+
${jsonUsageCached(gradingResult, gradingPath, gradingCachePath)}
|
|
272
|
+
) as grading_cached_tokens,
|
|
273
|
+
SUM(
|
|
274
|
+
${jsonUsageRequests(response, internalGradingPath)} +
|
|
275
|
+
${jsonUsageRequests(gradingResult, gradingPath, gradingCachePath)}
|
|
276
|
+
) as grading_num_requests,
|
|
277
|
+
SUM(
|
|
278
|
+
CASE
|
|
279
|
+
WHEN json_extract(response, ${incurredTargetPath}) IS NOT NULL
|
|
280
|
+
OR json_extract(grading_result, ${incurredGradingPath}) IS NOT NULL
|
|
281
|
+
OR COALESCE(json_extract(response, ${responseCachePath}), 0) = 1
|
|
282
|
+
OR COALESCE(json_extract(grading_result, ${gradingCachePath}), 0) = 1
|
|
283
|
+
THEN 1
|
|
284
|
+
ELSE 0
|
|
285
|
+
END
|
|
286
|
+
) as has_incurred_usage,
|
|
287
|
+
SUM(${incurredTargetUsage("total")}) as incurred_total_tokens,
|
|
288
|
+
SUM(${incurredTargetUsage("prompt")}) as incurred_prompt_tokens,
|
|
289
|
+
SUM(${incurredTargetUsage("completion")}) as incurred_completion_tokens,
|
|
290
|
+
SUM(${incurredTargetUsage("cached")}) as incurred_cached_tokens,
|
|
291
|
+
SUM(${incurredTargetUsage("numRequests")}) as incurred_num_requests,
|
|
292
|
+
SUM(${incurredAttackerUsage("total")}) as incurred_attacker_total_tokens,
|
|
293
|
+
SUM(${incurredAttackerUsage("prompt")}) as incurred_attacker_prompt_tokens,
|
|
294
|
+
SUM(${incurredAttackerUsage("completion")}) as incurred_attacker_completion_tokens,
|
|
295
|
+
SUM(${incurredAttackerUsage("cached")}) as incurred_attacker_cached_tokens,
|
|
296
|
+
SUM(${incurredAttackerUsage("numRequests")}) as incurred_attacker_num_requests,
|
|
297
|
+
SUM(
|
|
298
|
+
${incurredInternalGradingUsage("total")} + ${incurredGradingUsage("total")}
|
|
299
|
+
) as incurred_grading_total_tokens,
|
|
300
|
+
SUM(
|
|
301
|
+
${incurredInternalGradingUsage("prompt")} + ${incurredGradingUsage("prompt")}
|
|
302
|
+
) as incurred_grading_prompt_tokens,
|
|
303
|
+
SUM(
|
|
304
|
+
${incurredInternalGradingUsage("completion")} + ${incurredGradingUsage("completion")}
|
|
305
|
+
) as incurred_grading_completion_tokens,
|
|
306
|
+
SUM(
|
|
307
|
+
${incurredInternalGradingUsage("cached")} + ${incurredGradingUsage("cached")}
|
|
308
|
+
) as incurred_grading_cached_tokens,
|
|
309
|
+
SUM(
|
|
310
|
+
${incurredInternalGradingUsage("numRequests")} + ${incurredGradingUsage("numRequests")}
|
|
311
|
+
) as incurred_grading_num_requests
|
|
312
|
+
FROM eval_results
|
|
313
|
+
WHERE ${whereSql}
|
|
314
|
+
GROUP BY prompt_idx
|
|
315
|
+
ORDER BY prompt_idx
|
|
316
|
+
`;
|
|
317
|
+
const basicResults = await db.all(basicMetricsQuery);
|
|
318
|
+
for (const row of basicResults) {
|
|
319
|
+
const idx = row.prompt_idx;
|
|
320
|
+
if (idx < 0 || idx >= numPrompts) {
|
|
321
|
+
logger.warn(`Invalid prompt_idx ${idx}, expected 0-${numPrompts - 1}`);
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
metrics[idx] = {
|
|
325
|
+
score: row.total_score || 0,
|
|
326
|
+
testPassCount: row.pass_count || 0,
|
|
327
|
+
testFailCount: row.fail_count || 0,
|
|
328
|
+
testErrorCount: row.error_count || 0,
|
|
329
|
+
testCacheHitCount: row.cache_hit_count || 0,
|
|
330
|
+
totalLatencyMs: row.total_latency || 0,
|
|
331
|
+
cost: row.total_cost || 0,
|
|
332
|
+
...row.has_incurred_cost ? { incurredCost: row.incurred_cost || 0 } : {},
|
|
333
|
+
tokenUsage: getFilteredTokenUsage(row),
|
|
334
|
+
namedScores: {},
|
|
335
|
+
namedScoresCount: {},
|
|
336
|
+
namedScoreWeights: {},
|
|
337
|
+
assertPassCount: 0,
|
|
338
|
+
assertFailCount: 0
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
await aggregateNamedScores(metrics, whereSql);
|
|
342
|
+
await aggregateAssertions(metrics, whereSql);
|
|
343
|
+
logger.debug("Filtered metrics calculated", {
|
|
344
|
+
numPrompts,
|
|
345
|
+
metricsCount: basicResults.length
|
|
346
|
+
});
|
|
347
|
+
return metrics;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Aggregate named scores using SQL json_each().
|
|
351
|
+
* This is MUCH more efficient than fetching all results and parsing in JavaScript.
|
|
352
|
+
*
|
|
353
|
+
* SECURITY: Uses parameterized SQL query via Drizzle's sql template strings.
|
|
354
|
+
*
|
|
355
|
+
* Uses SQLite's json_each() to parse JSON in the database, avoiding the need
|
|
356
|
+
* to fetch potentially thousands of rows into memory.
|
|
357
|
+
*/
|
|
358
|
+
async function aggregateNamedScores(metrics, whereSql) {
|
|
359
|
+
const db = await getDb();
|
|
360
|
+
const query = sql`
|
|
361
|
+
SELECT
|
|
362
|
+
prompt_idx,
|
|
363
|
+
score_entries.key as metric_name,
|
|
364
|
+
SUM(
|
|
365
|
+
CASE
|
|
366
|
+
WHEN weight_entries.value IS NOT NULL THEN
|
|
367
|
+
CAST(score_entries.value AS REAL) * CAST(weight_entries.value AS REAL)
|
|
368
|
+
ELSE CAST(score_entries.value AS REAL)
|
|
369
|
+
END
|
|
370
|
+
) as metric_sum,
|
|
371
|
+
COUNT(*) as metric_count,
|
|
372
|
+
SUM(
|
|
373
|
+
CASE
|
|
374
|
+
WHEN weight_entries.value IS NOT NULL THEN CAST(weight_entries.value AS REAL)
|
|
375
|
+
ELSE 1
|
|
376
|
+
END
|
|
377
|
+
) as metric_weight_total
|
|
378
|
+
FROM eval_results
|
|
379
|
+
JOIN json_each(eval_results.named_scores) as score_entries
|
|
380
|
+
LEFT JOIN json_each(
|
|
381
|
+
CASE
|
|
382
|
+
WHEN grading_result IS NOT NULL
|
|
383
|
+
AND json_valid(grading_result)
|
|
384
|
+
AND json_type(json_extract(grading_result, '$.namedScoreWeights')) = 'object'
|
|
385
|
+
THEN json_extract(grading_result, '$.namedScoreWeights')
|
|
386
|
+
ELSE json('{}')
|
|
387
|
+
END
|
|
388
|
+
) as weight_entries
|
|
389
|
+
ON weight_entries.key = score_entries.key
|
|
390
|
+
WHERE ${whereSql}
|
|
391
|
+
AND named_scores IS NOT NULL
|
|
392
|
+
AND json_valid(named_scores)
|
|
393
|
+
GROUP BY prompt_idx, score_entries.key
|
|
394
|
+
`;
|
|
395
|
+
const results = await db.all(query);
|
|
396
|
+
for (const row of results) {
|
|
397
|
+
const idx = row.prompt_idx;
|
|
398
|
+
if (idx >= 0 && idx < metrics.length && metrics[idx]) {
|
|
399
|
+
metrics[idx].namedScores[row.metric_name] = row.metric_sum;
|
|
400
|
+
metrics[idx].namedScoresCount[row.metric_name] = row.metric_count;
|
|
401
|
+
metrics[idx].namedScoreWeights ||= {};
|
|
402
|
+
metrics[idx].namedScoreWeights[row.metric_name] = row.metric_weight_total;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Aggregate assertion counts using SQL json_each().
|
|
408
|
+
* This requires nested JSON extraction for componentResults.
|
|
409
|
+
*
|
|
410
|
+
* SECURITY: Uses parameterized SQL query via Drizzle's sql template strings.
|
|
411
|
+
*
|
|
412
|
+
* The grading_result structure is:
|
|
413
|
+
* {
|
|
414
|
+
* "componentResults": [
|
|
415
|
+
* {"pass": true, "assertion": {...}},
|
|
416
|
+
* {"pass": false, "assertion": {...}}
|
|
417
|
+
* ]
|
|
418
|
+
* }
|
|
419
|
+
*
|
|
420
|
+
* We need to count pass=true vs pass=false across all results.
|
|
421
|
+
*/
|
|
422
|
+
async function aggregateAssertions(metrics, whereSql) {
|
|
423
|
+
const db = await getDb();
|
|
424
|
+
const query = sql`
|
|
425
|
+
SELECT
|
|
426
|
+
prompt_idx,
|
|
427
|
+
SUM(
|
|
428
|
+
CASE
|
|
429
|
+
WHEN json_valid(grading_result) AND json_type(json_extract(grading_result, '$.componentResults')) = 'array' THEN
|
|
430
|
+
(
|
|
431
|
+
SELECT COUNT(*)
|
|
432
|
+
FROM json_each(json_extract(grading_result, '$.componentResults'))
|
|
433
|
+
WHERE CAST(json_extract(json_each.value, '$.pass') AS INTEGER) = 1
|
|
434
|
+
)
|
|
435
|
+
ELSE 0
|
|
436
|
+
END
|
|
437
|
+
) as assert_pass_count,
|
|
438
|
+
SUM(
|
|
439
|
+
CASE
|
|
440
|
+
WHEN json_valid(grading_result) AND json_type(json_extract(grading_result, '$.componentResults')) = 'array' THEN
|
|
441
|
+
(
|
|
442
|
+
SELECT COUNT(*)
|
|
443
|
+
FROM json_each(json_extract(grading_result, '$.componentResults'))
|
|
444
|
+
WHERE CAST(json_extract(json_each.value, '$.pass') AS INTEGER) = 0
|
|
445
|
+
)
|
|
446
|
+
ELSE 0
|
|
447
|
+
END
|
|
448
|
+
) as assert_fail_count
|
|
449
|
+
FROM eval_results
|
|
450
|
+
WHERE ${whereSql}
|
|
451
|
+
AND grading_result IS NOT NULL
|
|
452
|
+
GROUP BY prompt_idx
|
|
453
|
+
`;
|
|
454
|
+
const results = await db.all(query);
|
|
455
|
+
for (const row of results) {
|
|
456
|
+
const idx = row.prompt_idx;
|
|
457
|
+
if (idx >= 0 && idx < metrics.length && metrics[idx]) {
|
|
458
|
+
metrics[idx].assertPassCount = row.assert_pass_count || 0;
|
|
459
|
+
metrics[idx].assertFailCount = row.assert_fail_count || 0;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Create empty metrics array initialized with zeros.
|
|
465
|
+
* Used as fallback when calculation fails or no results found.
|
|
466
|
+
*/
|
|
467
|
+
function createEmptyMetricsArray(numPrompts) {
|
|
468
|
+
return Array.from({ length: numPrompts }, () => ({
|
|
469
|
+
score: 0,
|
|
470
|
+
testPassCount: 0,
|
|
471
|
+
testFailCount: 0,
|
|
472
|
+
testErrorCount: 0,
|
|
473
|
+
testCacheHitCount: 0,
|
|
474
|
+
assertPassCount: 0,
|
|
475
|
+
assertFailCount: 0,
|
|
476
|
+
totalLatencyMs: 0,
|
|
477
|
+
tokenUsage: {
|
|
478
|
+
total: 0,
|
|
479
|
+
prompt: 0,
|
|
480
|
+
completion: 0,
|
|
481
|
+
cached: 0,
|
|
482
|
+
numRequests: 0
|
|
483
|
+
},
|
|
484
|
+
namedScores: {},
|
|
485
|
+
namedScoresCount: {},
|
|
486
|
+
namedScoreWeights: {},
|
|
487
|
+
cost: 0
|
|
488
|
+
}));
|
|
489
|
+
}
|
|
490
|
+
//#endregion
|
|
491
|
+
//#region src/presentation/evalTableCells.ts
|
|
492
|
+
function getTableCellText(result) {
|
|
493
|
+
let resultText;
|
|
494
|
+
const rawOutput = result.response?.output;
|
|
495
|
+
let outputTextDisplay;
|
|
496
|
+
if (rawOutput !== null && typeof rawOutput === "object") outputTextDisplay = JSON.stringify(rawOutput);
|
|
497
|
+
else if (rawOutput == null || rawOutput === "") outputTextDisplay = result.error || "";
|
|
498
|
+
else outputTextDisplay = String(rawOutput);
|
|
499
|
+
if (result.testCase.assert) {
|
|
500
|
+
if (result.success) resultText = `${outputTextDisplay || result.error || ""}`;
|
|
501
|
+
else resultText = `${outputTextDisplay}`;
|
|
502
|
+
} else if (result.error) resultText = `${result.error}`;
|
|
503
|
+
else resultText = outputTextDisplay;
|
|
504
|
+
return resultText;
|
|
505
|
+
}
|
|
506
|
+
function getTableCellMedia(result) {
|
|
507
|
+
return {
|
|
508
|
+
audio: result.response?.audio ? {
|
|
509
|
+
id: result.response.audio.id,
|
|
510
|
+
expiresAt: result.response.audio.expiresAt,
|
|
511
|
+
data: result.response.audio.data,
|
|
512
|
+
blobRef: result.response.audio.blobRef,
|
|
513
|
+
transcript: result.response.audio.transcript,
|
|
514
|
+
format: result.response.audio.format,
|
|
515
|
+
sampleRate: result.response.audio.sampleRate,
|
|
516
|
+
channels: result.response.audio.channels,
|
|
517
|
+
duration: result.response.audio.duration
|
|
518
|
+
} : void 0,
|
|
519
|
+
video: result.response?.video ? {
|
|
520
|
+
id: result.response.video.id,
|
|
521
|
+
blobRef: result.response.video.blobRef,
|
|
522
|
+
storageRef: result.response.video.storageRef,
|
|
523
|
+
url: result.response.video.url,
|
|
524
|
+
format: result.response.video.format,
|
|
525
|
+
size: result.response.video.size,
|
|
526
|
+
duration: result.response.video.duration,
|
|
527
|
+
thumbnail: result.response.video.thumbnail,
|
|
528
|
+
spritesheet: result.response.video.spritesheet,
|
|
529
|
+
model: result.response.video.model,
|
|
530
|
+
aspectRatio: result.response.video.aspectRatio,
|
|
531
|
+
resolution: result.response.video.resolution
|
|
532
|
+
} : void 0,
|
|
533
|
+
images: result.response?.images?.map((img) => ({
|
|
534
|
+
data: img.data,
|
|
535
|
+
blobRef: img.blobRef,
|
|
536
|
+
mimeType: img.mimeType
|
|
537
|
+
}))
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
//#endregion
|
|
541
|
+
//#region src/presentation/evalResults.ts
|
|
542
|
+
/** Convert version 4+ results to display rows and ordered variable columns. */
|
|
543
|
+
function convertResultsToTable(eval_) {
|
|
544
|
+
invariant(eval_.prompts, `Prompts are required in this version of the results file, this needs to be results file version >= 4, version: ${eval_.version}`);
|
|
545
|
+
const results = eval_.results;
|
|
546
|
+
const rawPersistedVars = eval_.vars;
|
|
547
|
+
if (rawPersistedVars !== void 0 && !Array.isArray(rawPersistedVars)) logger.warn(`[convertResultsToTable] eval.vars is ${typeof rawPersistedVars}, not string[]; falling back to alphabetical ordering`);
|
|
548
|
+
const persistedVarSet = new Set(Array.isArray(rawPersistedVars) ? rawPersistedVars : []);
|
|
549
|
+
const persistedVars = Array.from(persistedVarSet);
|
|
550
|
+
const varsForHeader = new Set(persistedVars);
|
|
551
|
+
const varValuesForRow = /* @__PURE__ */ new Map();
|
|
552
|
+
const rowMap = {};
|
|
553
|
+
for (const result of results.results) {
|
|
554
|
+
for (const varName of Object.keys(result.vars || {})) varsForHeader.add(varName);
|
|
555
|
+
const row = rowMap[result.testIdx] || {
|
|
556
|
+
description: result.description || void 0,
|
|
557
|
+
outputs: [],
|
|
558
|
+
vars: [],
|
|
559
|
+
test: result.testCase
|
|
560
|
+
};
|
|
561
|
+
const actualPrompt = getActualPrompt(result.response) || result.metadata?.redteamFinalPrompt;
|
|
562
|
+
if (result.vars && actualPrompt) {
|
|
563
|
+
const varKeys = Object.keys(result.vars);
|
|
564
|
+
if (varKeys.length === 1 && varKeys[0] !== "harmCategory") result.vars[varKeys[0]] = actualPrompt;
|
|
565
|
+
else if (varKeys.length > 1) {
|
|
566
|
+
const keyToUpdate = [
|
|
567
|
+
"prompt",
|
|
568
|
+
"query",
|
|
569
|
+
"question"
|
|
570
|
+
].find((key) => result.vars[key]);
|
|
571
|
+
if (keyToUpdate) result.vars[keyToUpdate] = actualPrompt;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
if (!result.vars?.sessionId) {
|
|
575
|
+
const metadataSessionIds = result.metadata?.sessionIds;
|
|
576
|
+
if (Array.isArray(metadataSessionIds) && metadataSessionIds.length > 0) {
|
|
577
|
+
result.vars = result.vars || {};
|
|
578
|
+
result.vars.sessionId = metadataSessionIds.filter((id) => id != null && id !== "").map(String).join("\n");
|
|
579
|
+
varsForHeader.add("sessionId");
|
|
580
|
+
} else if (result.metadata?.sessionId) {
|
|
581
|
+
result.vars = result.vars || {};
|
|
582
|
+
result.vars.sessionId = result.metadata.sessionId;
|
|
583
|
+
varsForHeader.add("sessionId");
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
const transformDisplayVars = result.response?.metadata?.transformDisplayVars;
|
|
587
|
+
if (transformDisplayVars) {
|
|
588
|
+
result.vars = result.vars || {};
|
|
589
|
+
for (const [key, value] of Object.entries(transformDisplayVars)) if (!(key in result.vars)) {
|
|
590
|
+
result.vars[key] = value;
|
|
591
|
+
varsForHeader.add(key);
|
|
592
|
+
} else if (result.vars[key] !== value) logger.debug(`[convertResultsToTable] transformDisplayVars key '${key}' collides with result.vars; preserving original value`);
|
|
593
|
+
}
|
|
594
|
+
varValuesForRow.set(result.testIdx, result.vars);
|
|
595
|
+
rowMap[result.testIdx] = row;
|
|
596
|
+
const resultText = getTableCellText(result);
|
|
597
|
+
row.outputs[result.promptIdx] = {
|
|
598
|
+
id: result.id || `${result.testIdx}-${result.promptIdx}`,
|
|
599
|
+
...result,
|
|
600
|
+
text: resultText || "",
|
|
601
|
+
prompt: result.prompt.raw,
|
|
602
|
+
provider: result.provider?.label || result.provider?.id || "unknown provider",
|
|
603
|
+
pass: result.success,
|
|
604
|
+
failureReason: result.failureReason,
|
|
605
|
+
cost: result.cost || 0,
|
|
606
|
+
tokenUsage: result.tokenUsage,
|
|
607
|
+
...getTableCellMedia(result)
|
|
608
|
+
};
|
|
609
|
+
invariant(result.promptId, "Prompt ID is required");
|
|
610
|
+
row.testIdx = result.testIdx;
|
|
611
|
+
}
|
|
612
|
+
const rows = Object.values(rowMap);
|
|
613
|
+
const additionalVars = [...varsForHeader].filter((name) => !persistedVarSet.has(name)).sort();
|
|
614
|
+
const orderedVars = persistedVars.length > 0 ? [...persistedVars, ...additionalVars] : additionalVars;
|
|
615
|
+
for (const row of rows) row.vars = orderedVars.map((varName) => {
|
|
616
|
+
const varValue = varValuesForRow.get(row.testIdx)?.[varName] ?? "";
|
|
617
|
+
if (typeof varValue === "string") return varValue;
|
|
618
|
+
return JSON.stringify(varValue, null, 2);
|
|
619
|
+
});
|
|
620
|
+
return {
|
|
621
|
+
head: {
|
|
622
|
+
prompts: eval_.prompts,
|
|
623
|
+
vars: orderedVars
|
|
624
|
+
},
|
|
625
|
+
body: rows
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
//#endregion
|
|
629
|
+
//#region src/util/eval/repeatStability.ts
|
|
630
|
+
const WILSON_Z_95 = 1.959963984540054;
|
|
631
|
+
const ERROR_FAILURE_REASON = 2;
|
|
632
|
+
function getWilsonScoreInterval(passed, total) {
|
|
633
|
+
if (total <= 0 || passed < 0 || passed > total) return;
|
|
634
|
+
const proportion = passed / total;
|
|
635
|
+
const zSquared = WILSON_Z_95 ** 2;
|
|
636
|
+
const denominator = 1 + zSquared / total;
|
|
637
|
+
const center = (proportion + zSquared / (2 * total)) / denominator;
|
|
638
|
+
const margin = WILSON_Z_95 / denominator * Math.sqrt(proportion * (1 - proportion) / total + zSquared / (4 * total ** 2));
|
|
639
|
+
return {
|
|
640
|
+
confidenceLevel: .95,
|
|
641
|
+
lower: Math.max(0, center - margin),
|
|
642
|
+
upper: Math.min(1, center + margin)
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
function isCachedResult(result) {
|
|
646
|
+
if (result.response?.cached === true) return true;
|
|
647
|
+
if (!result.gradingResult) return false;
|
|
648
|
+
const pending = [result.gradingResult];
|
|
649
|
+
const visited = /* @__PURE__ */ new Set();
|
|
650
|
+
for (let index = 0; index < pending.length; index++) {
|
|
651
|
+
const gradingResult = pending[index];
|
|
652
|
+
if (!gradingResult || typeof gradingResult !== "object" || visited.has(gradingResult)) continue;
|
|
653
|
+
visited.add(gradingResult);
|
|
654
|
+
if (gradingResult.metadata?.cachedResponse === true) return true;
|
|
655
|
+
const components = gradingResult.componentResults;
|
|
656
|
+
if (Array.isArray(components)) for (let childIndex = 0; childIndex < components.length; childIndex++) pending.push(components[childIndex]);
|
|
657
|
+
}
|
|
658
|
+
return false;
|
|
659
|
+
}
|
|
660
|
+
function getGroupKey(result) {
|
|
661
|
+
return `${result.repeatGroupId}\u0000${result.promptIdx}\u0000${result.provider.id}\u0000${result.provider.label}`;
|
|
662
|
+
}
|
|
663
|
+
var RepeatStabilityCalculator = class {
|
|
664
|
+
groups = /* @__PURE__ */ new Map();
|
|
665
|
+
addResults(results) {
|
|
666
|
+
for (const result of results) this.addResult(result);
|
|
667
|
+
}
|
|
668
|
+
addResult(result) {
|
|
669
|
+
if (!result.repeatGroupId || result.repeatIndex === void 0 || !Number.isInteger(result.repeatIndex) || result.repeatIndex < 0) return;
|
|
670
|
+
const key = getGroupKey(result);
|
|
671
|
+
const group = this.groups.get(key) ?? {
|
|
672
|
+
repeatGroupId: result.repeatGroupId,
|
|
673
|
+
promptIdx: result.promptIdx,
|
|
674
|
+
provider: {
|
|
675
|
+
id: result.provider.id,
|
|
676
|
+
label: result.provider.label
|
|
677
|
+
},
|
|
678
|
+
description: result.description ?? result.testCase.description,
|
|
679
|
+
promptLabel: result.prompt.label,
|
|
680
|
+
repetitions: 0,
|
|
681
|
+
passed: 0,
|
|
682
|
+
failed: 0,
|
|
683
|
+
errors: 0,
|
|
684
|
+
cached: 0,
|
|
685
|
+
scored: 0,
|
|
686
|
+
unstable: false
|
|
687
|
+
};
|
|
688
|
+
group.repetitions++;
|
|
689
|
+
if (isCachedResult(result)) group.cached++;
|
|
690
|
+
if (result.failureReason === ERROR_FAILURE_REASON) group.errors++;
|
|
691
|
+
else if (result.success) {
|
|
692
|
+
group.passed++;
|
|
693
|
+
group.scored++;
|
|
694
|
+
} else {
|
|
695
|
+
group.failed++;
|
|
696
|
+
group.scored++;
|
|
697
|
+
}
|
|
698
|
+
group.unstable = group.passed > 0 && group.failed > 0;
|
|
699
|
+
this.groups.set(key, group);
|
|
700
|
+
}
|
|
701
|
+
getSummary() {
|
|
702
|
+
if (this.groups.size === 0) return;
|
|
703
|
+
const groups = Array.from(this.groups.values()).map(({ scored, ...group }) => ({
|
|
704
|
+
...group,
|
|
705
|
+
...scored > 0 && { passRate: group.passed / scored },
|
|
706
|
+
...scored > 0 && group.cached === 0 && { passRateConfidenceInterval: getWilsonScoreInterval(group.passed, scored) }
|
|
707
|
+
}));
|
|
708
|
+
groups.sort((a, b) => a.repeatGroupId.localeCompare(b.repeatGroupId) || a.promptIdx - b.promptIdx || (a.provider.id ?? "").localeCompare(b.provider.id ?? "") || (a.provider.label ?? "").localeCompare(b.provider.label ?? ""));
|
|
709
|
+
return {
|
|
710
|
+
totalGroups: groups.length,
|
|
711
|
+
unstableGroups: groups.filter((group) => group.unstable).length,
|
|
712
|
+
groupsWithErrors: groups.filter((group) => group.errors > 0).length,
|
|
713
|
+
cachedResults: groups.reduce((total, group) => total + group.cached, 0),
|
|
714
|
+
groups
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
function calculateRepeatStability(results) {
|
|
719
|
+
const calculator = new RepeatStabilityCalculator();
|
|
720
|
+
calculator.addResults(results);
|
|
721
|
+
return calculator.getSummary();
|
|
722
|
+
}
|
|
723
|
+
//#endregion
|
|
724
|
+
//#region src/util/exportToFile/index.ts
|
|
725
|
+
function convertEvalResultToTableCell(result) {
|
|
726
|
+
const resultText = getTableCellText(result);
|
|
727
|
+
return {
|
|
728
|
+
...result,
|
|
729
|
+
id: result.id || `${result.testIdx}-${result.promptIdx}`,
|
|
730
|
+
text: resultText || "",
|
|
731
|
+
prompt: result.prompt.raw,
|
|
732
|
+
provider: result.provider?.label || result.provider?.id || "unknown provider",
|
|
733
|
+
pass: result.success,
|
|
734
|
+
cost: result.cost || 0,
|
|
735
|
+
...getTableCellMedia(result)
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
function convertTestResultsToTableRow(results, varsForHeader) {
|
|
739
|
+
const row = {
|
|
740
|
+
description: results[0].description || void 0,
|
|
741
|
+
outputs: [],
|
|
742
|
+
vars: Object.values(varsForHeader).map((varName) => {
|
|
743
|
+
if (varName === "sessionId") {
|
|
744
|
+
const sessionIdFromVars = results[0].testCase.vars?.sessionId;
|
|
745
|
+
if (sessionIdFromVars != null && sessionIdFromVars !== "") return typeof sessionIdFromVars === "string" ? sessionIdFromVars : JSON.stringify(sessionIdFromVars);
|
|
746
|
+
const metadataSessionIds = results[0].metadata?.sessionIds;
|
|
747
|
+
if (Array.isArray(metadataSessionIds) && metadataSessionIds.length > 0) return metadataSessionIds.filter((id) => id != null && id !== "").map(String).join("\n");
|
|
748
|
+
const metadataSessionId = results[0].metadata?.sessionId;
|
|
749
|
+
if (metadataSessionId != null) return typeof metadataSessionId === "string" ? metadataSessionId : JSON.stringify(metadataSessionId);
|
|
750
|
+
return "";
|
|
751
|
+
}
|
|
752
|
+
const varValue = results[0].testCase.vars?.[varName] ?? "";
|
|
753
|
+
if (typeof varValue === "string") return varValue;
|
|
754
|
+
return JSON.stringify(varValue);
|
|
755
|
+
}),
|
|
756
|
+
test: results[0].testCase,
|
|
757
|
+
testIdx: results[0].testIdx
|
|
758
|
+
};
|
|
759
|
+
for (const result of results) row.outputs[result.promptIdx] = convertEvalResultToTableCell(result);
|
|
760
|
+
return row;
|
|
761
|
+
}
|
|
762
|
+
//#endregion
|
|
763
|
+
//#region src/models/eval.ts
|
|
764
|
+
function createEvalId(createdAt = /* @__PURE__ */ new Date()) {
|
|
765
|
+
return `eval-${randomSequence(3)}-${createdAt.toISOString().slice(0, 19)}`;
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Escapes a key for use in a JSON path expression.
|
|
769
|
+
* Handles backslashes and double quotes which have special meaning in JSON paths.
|
|
770
|
+
*/
|
|
771
|
+
function escapeJsonPathKey(key) {
|
|
772
|
+
return key.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Builds a JSON path for use as a bound SQLite json_extract() parameter.
|
|
776
|
+
*
|
|
777
|
+
* The field name still needs JSON-path escaping so special characters remain
|
|
778
|
+
* inside the quoted key. SQL safety comes from passing the returned path through
|
|
779
|
+
* Drizzle's `sql` templates as a value, never as raw SQL.
|
|
780
|
+
*/
|
|
781
|
+
function buildSafeJsonPath(field) {
|
|
782
|
+
return `$."${escapeJsonPathKey(field)}"`;
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Combines multiple filter conditions using their associated logic operators (AND/OR).
|
|
786
|
+
*
|
|
787
|
+
* @param filterConditions - Array of conditions with their logic operators
|
|
788
|
+
* @returns A single SQL fragment combining all conditions, or null if empty
|
|
789
|
+
*/
|
|
790
|
+
function combineFilterConditions(filterConditions) {
|
|
791
|
+
if (filterConditions.length === 0) return null;
|
|
792
|
+
if (filterConditions.length === 1) return filterConditions[0].condition;
|
|
793
|
+
return filterConditions.reduce((acc, { condition: cond, logicOperator }, idx) => {
|
|
794
|
+
if (idx === 0) return cond;
|
|
795
|
+
return typeof logicOperator === "string" && logicOperator.toUpperCase() === "OR" ? sql`${acc} OR ${cond}` : sql`${acc} AND ${cond}`;
|
|
796
|
+
}, filterConditions[0].condition);
|
|
797
|
+
}
|
|
798
|
+
var EvalQueries = class {
|
|
799
|
+
static async getVarsFromEvals(evals) {
|
|
800
|
+
const db = await getDb();
|
|
801
|
+
if (evals.length === 0) return {};
|
|
802
|
+
const evalIds = evals.map((e) => e.id);
|
|
803
|
+
const query = sql`
|
|
804
|
+
SELECT DISTINCT j.key, eval_id
|
|
805
|
+
FROM (
|
|
806
|
+
SELECT eval_id, json_extract(eval_results.test_case, '$.vars') as vars
|
|
807
|
+
FROM eval_results
|
|
808
|
+
WHERE eval_id IN (${sql.join(evalIds, sql`, `)})
|
|
809
|
+
) t, json_each(t.vars) j
|
|
810
|
+
`;
|
|
811
|
+
const vars = (await db.all(query)).reduce((acc, r) => {
|
|
812
|
+
acc[r.eval_id] = acc[r.eval_id] || [];
|
|
813
|
+
acc[r.eval_id].push(r.key);
|
|
814
|
+
return acc;
|
|
815
|
+
}, {});
|
|
816
|
+
for (const list of Object.values(vars)) list.sort();
|
|
817
|
+
return vars;
|
|
818
|
+
}
|
|
819
|
+
static async getVarsFromEval(evalId) {
|
|
820
|
+
const db = await getDb();
|
|
821
|
+
const query = sql`
|
|
822
|
+
SELECT DISTINCT j.key
|
|
823
|
+
FROM (
|
|
824
|
+
SELECT json_extract(eval_results.test_case, '$.vars') as vars
|
|
825
|
+
FROM eval_results
|
|
826
|
+
WHERE eval_results.eval_id = ${evalId}
|
|
827
|
+
) t, json_each(t.vars) j
|
|
828
|
+
`;
|
|
829
|
+
return (await db.all(query)).map((r) => r.key).sort();
|
|
830
|
+
}
|
|
831
|
+
static async setVars(evalId, vars) {
|
|
832
|
+
const db = await getDb();
|
|
833
|
+
try {
|
|
834
|
+
await db.update(evalsTable).set({ vars }).where(eq(evalsTable.id, evalId)).run();
|
|
835
|
+
} catch (e) {
|
|
836
|
+
logger.error(`Error setting vars: ${vars} for eval ${evalId}: ${e}`);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
static async getMetadataKeysFromEval(evalId, comparisonEvalIds = []) {
|
|
840
|
+
const db = await getDb();
|
|
841
|
+
try {
|
|
842
|
+
const allEvalIds = [evalId, ...comparisonEvalIds];
|
|
843
|
+
const query = sql`
|
|
844
|
+
SELECT DISTINCT j.key FROM (
|
|
845
|
+
SELECT metadata FROM eval_results
|
|
846
|
+
WHERE eval_id IN (${sql.join(allEvalIds, sql`, `)})
|
|
847
|
+
AND metadata IS NOT NULL
|
|
848
|
+
AND metadata != '{}'
|
|
849
|
+
AND json_valid(metadata)
|
|
850
|
+
LIMIT 10000
|
|
851
|
+
) t, json_each(t.metadata) j
|
|
852
|
+
ORDER BY j.key
|
|
853
|
+
LIMIT 1000
|
|
854
|
+
`;
|
|
855
|
+
return (await db.all(query)).map((r) => r.key).filter((key) => key !== PROMPTFOO_METADATA_KEY);
|
|
856
|
+
} catch (error) {
|
|
857
|
+
logger.error(`Error fetching metadata keys for eval ${evalId} and comparisons [${comparisonEvalIds.join(", ")}]: ${error}`);
|
|
858
|
+
return [];
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* Queries all unique metadata values for a given metadata key.
|
|
863
|
+
* @param evalId - The ID of the eval to get the metadata values from.
|
|
864
|
+
* @param key - The key of the metadata to get the values from.
|
|
865
|
+
* @returns An array of unique metadata values.
|
|
866
|
+
*/
|
|
867
|
+
static async getMetadataValuesFromEval(evalId, key) {
|
|
868
|
+
const db = await getDb();
|
|
869
|
+
const trimmedKey = key.trim();
|
|
870
|
+
if (!trimmedKey) return [];
|
|
871
|
+
if (trimmedKey === "__promptfoo" || trimmedKey.startsWith(`__promptfoo.`)) return [];
|
|
872
|
+
try {
|
|
873
|
+
const jsonPath = buildSafeJsonPath(trimmedKey);
|
|
874
|
+
const query = sql`
|
|
875
|
+
SELECT DISTINCT
|
|
876
|
+
json_extract(${evalResultsTable.metadata}, ${jsonPath}) AS value
|
|
877
|
+
FROM ${evalResultsTable}
|
|
878
|
+
WHERE ${evalResultsTable.evalId} = ${evalId}
|
|
879
|
+
AND ${evalResultsTable.metadata} IS NOT NULL
|
|
880
|
+
AND ${evalResultsTable.metadata} != '{}'
|
|
881
|
+
AND json_valid(${evalResultsTable.metadata})
|
|
882
|
+
AND json_extract(${evalResultsTable.metadata}, ${jsonPath}) IS NOT NULL
|
|
883
|
+
ORDER BY value
|
|
884
|
+
LIMIT 1000
|
|
885
|
+
`;
|
|
886
|
+
const values = (await db.all(query)).map(({ value }) => String(value).trim()).filter((value) => value.length > 0);
|
|
887
|
+
return Array.from(new Set(values));
|
|
888
|
+
} catch (error) {
|
|
889
|
+
logger.error(`Error fetching metadata values for eval ${evalId} and key ${trimmedKey}: ${error instanceof Error ? error.message : String(error)}`);
|
|
890
|
+
return [];
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
};
|
|
894
|
+
var Eval = class Eval {
|
|
895
|
+
id;
|
|
896
|
+
createdAt;
|
|
897
|
+
author;
|
|
898
|
+
description;
|
|
899
|
+
config;
|
|
900
|
+
results;
|
|
901
|
+
datasetId;
|
|
902
|
+
prompts;
|
|
903
|
+
oldResults;
|
|
904
|
+
persisted;
|
|
905
|
+
vars;
|
|
906
|
+
_resultsLoaded = false;
|
|
907
|
+
runtimeOptions;
|
|
908
|
+
_shared = false;
|
|
909
|
+
resultPersistenceFailed = false;
|
|
910
|
+
/**
|
|
911
|
+
* The first non-transient HTTP status among the rows added in this run. It stands in for
|
|
912
|
+
* the database when that cannot be queried afterwards.
|
|
913
|
+
*/
|
|
914
|
+
observedTargetErrorStatus;
|
|
915
|
+
failedResults = /* @__PURE__ */ new Map();
|
|
916
|
+
failedEvalResults = /* @__PURE__ */ new Map();
|
|
917
|
+
finalJsonlResults = /* @__PURE__ */ new Map();
|
|
918
|
+
observedRepeatedResults = false;
|
|
919
|
+
/** Total wall-clock duration. For redteam evals: generationDurationMs + evaluationDurationMs.
|
|
920
|
+
* For non-redteam evals: equals evaluationDurationMs (generation phase is N/A). */
|
|
921
|
+
durationMs;
|
|
922
|
+
/** Time spent generating adversarial test cases (redteam only). */
|
|
923
|
+
generationDurationMs;
|
|
924
|
+
/** Time spent running the evaluation phase. */
|
|
925
|
+
evaluationDurationMs;
|
|
926
|
+
/**
|
|
927
|
+
* The shareable URL for this evaluation, if it has been shared.
|
|
928
|
+
* Set by the evaluate() function when sharing is enabled.
|
|
929
|
+
*/
|
|
930
|
+
shareableUrl;
|
|
931
|
+
static async latest() {
|
|
932
|
+
const db_results = await (await getDb()).select({ id: evalsTable.id }).from(evalsTable).orderBy(desc(evalsTable.createdAt)).limit(1);
|
|
933
|
+
if (db_results.length === 0) return;
|
|
934
|
+
return await Eval.findById(db_results[0].id);
|
|
935
|
+
}
|
|
936
|
+
static async findById(id) {
|
|
937
|
+
const db = await getDb();
|
|
938
|
+
const evalData = await db.select().from(evalsTable).where(eq(evalsTable.id, id)).all();
|
|
939
|
+
if (evalData.length === 0) return;
|
|
940
|
+
const datasetResults = await db.select({ datasetId: evalsToDatasetsTable.datasetId }).from(evalsToDatasetsTable).where(eq(evalsToDatasetsTable.evalId, id)).limit(1).all();
|
|
941
|
+
const eval_ = evalData[0];
|
|
942
|
+
const datasetId = datasetResults[0]?.datasetId;
|
|
943
|
+
const resultsObj = eval_.results;
|
|
944
|
+
const validateDuration = (raw) => typeof raw === "number" && Number.isFinite(raw) && raw >= 0 ? raw : void 0;
|
|
945
|
+
const rawDurationMs = validateDuration(resultsObj?.["durationMs"]);
|
|
946
|
+
const generationDurationMs = validateDuration(resultsObj?.["generationDurationMs"]);
|
|
947
|
+
const evaluationDurationMs = validateDuration(resultsObj?.["evaluationDurationMs"]);
|
|
948
|
+
const durationMs = rawDurationMs ?? (generationDurationMs != null || evaluationDurationMs != null ? (generationDurationMs ?? 0) + (evaluationDurationMs ?? 0) : void 0);
|
|
949
|
+
const evalInstance = new Eval(eval_.config, {
|
|
950
|
+
id: eval_.id,
|
|
951
|
+
createdAt: new Date(eval_.createdAt),
|
|
952
|
+
author: eval_.author,
|
|
953
|
+
description: eval_.description || void 0,
|
|
954
|
+
prompts: eval_.prompts || [],
|
|
955
|
+
datasetId,
|
|
956
|
+
persisted: true,
|
|
957
|
+
vars: eval_.vars || [],
|
|
958
|
+
runtimeOptions: eval_.runtimeOptions ?? void 0,
|
|
959
|
+
durationMs,
|
|
960
|
+
generationDurationMs,
|
|
961
|
+
evaluationDurationMs
|
|
962
|
+
});
|
|
963
|
+
if (eval_.results && "table" in eval_.results) evalInstance.oldResults = eval_.results;
|
|
964
|
+
if (!eval_.vars || eval_.vars.length === 0) {
|
|
965
|
+
const vars = await EvalQueries.getVarsFromEval(id);
|
|
966
|
+
evalInstance.setVars(vars);
|
|
967
|
+
await EvalQueries.setVars(id, vars);
|
|
968
|
+
}
|
|
969
|
+
return evalInstance;
|
|
970
|
+
}
|
|
971
|
+
static async getMany(limit = 100) {
|
|
972
|
+
return (await (await getDb()).select({
|
|
973
|
+
id: evalsTable.id,
|
|
974
|
+
createdAt: evalsTable.createdAt,
|
|
975
|
+
author: evalsTable.author,
|
|
976
|
+
description: evalsTable.description,
|
|
977
|
+
config: evalsTable.config,
|
|
978
|
+
prompts: evalsTable.prompts
|
|
979
|
+
}).from(evalsTable).limit(limit).orderBy(desc(evalsTable.createdAt)).all()).map((e) => new Eval(e.config, {
|
|
980
|
+
id: e.id,
|
|
981
|
+
createdAt: new Date(e.createdAt),
|
|
982
|
+
author: e.author,
|
|
983
|
+
description: e.description || void 0,
|
|
984
|
+
prompts: e.prompts || [],
|
|
985
|
+
persisted: true
|
|
986
|
+
}));
|
|
987
|
+
}
|
|
988
|
+
static async create(config, renderedPrompts, opts) {
|
|
989
|
+
const createdAt = opts?.createdAt || /* @__PURE__ */ new Date();
|
|
990
|
+
const evalId = opts?.id || createEvalId(createdAt);
|
|
991
|
+
const author = opts && "author" in opts ? opts.author ?? null : getAuthor();
|
|
992
|
+
const db = await getDb();
|
|
993
|
+
const datasetId = sha256(JSON.stringify(config.tests || []));
|
|
994
|
+
const durationResults = {
|
|
995
|
+
...opts?.durationMs !== void 0 && { durationMs: opts.durationMs },
|
|
996
|
+
...opts?.generationDurationMs !== void 0 && { generationDurationMs: opts.generationDurationMs },
|
|
997
|
+
...opts?.evaluationDurationMs !== void 0 && { evaluationDurationMs: opts.evaluationDurationMs }
|
|
998
|
+
};
|
|
999
|
+
await db.transaction(async (tx) => {
|
|
1000
|
+
await tx.insert(evalsTable).values({
|
|
1001
|
+
id: evalId,
|
|
1002
|
+
createdAt: createdAt.getTime(),
|
|
1003
|
+
author,
|
|
1004
|
+
description: config.description,
|
|
1005
|
+
config: sanitizeTracingConfigForPersistence(config),
|
|
1006
|
+
results: durationResults,
|
|
1007
|
+
vars: opts?.vars || [],
|
|
1008
|
+
runtimeOptions: sanitizeRuntimeOptions(opts?.runtimeOptions),
|
|
1009
|
+
prompts: opts?.completedPrompts || [],
|
|
1010
|
+
isRedteam: config.redteam !== void 0
|
|
1011
|
+
}).run();
|
|
1012
|
+
for (const prompt of renderedPrompts) {
|
|
1013
|
+
const label = prompt.label || prompt.display || prompt.raw;
|
|
1014
|
+
const promptId = hashPrompt(prompt);
|
|
1015
|
+
await tx.insert(promptsTable).values({
|
|
1016
|
+
id: promptId,
|
|
1017
|
+
prompt: label
|
|
1018
|
+
}).onConflictDoNothing().run();
|
|
1019
|
+
await tx.insert(evalsToPromptsTable).values({
|
|
1020
|
+
evalId,
|
|
1021
|
+
promptId
|
|
1022
|
+
}).onConflictDoNothing().run();
|
|
1023
|
+
logger.debug(`Inserting prompt ${promptId}`);
|
|
1024
|
+
}
|
|
1025
|
+
if (opts?.results && opts.results.length > 0) {
|
|
1026
|
+
const res = await tx.insert(evalResultsTable).values(opts.results?.map((r) => ({
|
|
1027
|
+
...r,
|
|
1028
|
+
metadata: persistTraceMetadata(persistRepeatMetadata(r.metadata, r.repeatIndex, r.repeatGroupId), r.traceId, r.evaluationId),
|
|
1029
|
+
evalId,
|
|
1030
|
+
id: crypto.randomUUID()
|
|
1031
|
+
}))).run();
|
|
1032
|
+
logger.debug(`Inserted ${res.rowsAffected} eval results`);
|
|
1033
|
+
}
|
|
1034
|
+
await tx.insert(datasetsTable).values({
|
|
1035
|
+
id: datasetId,
|
|
1036
|
+
tests: config.tests
|
|
1037
|
+
}).onConflictDoNothing().run();
|
|
1038
|
+
await tx.insert(evalsToDatasetsTable).values({
|
|
1039
|
+
evalId,
|
|
1040
|
+
datasetId
|
|
1041
|
+
}).onConflictDoNothing().run();
|
|
1042
|
+
logger.debug(`Inserting dataset ${datasetId}`);
|
|
1043
|
+
if (config.tags) for (const [tagKey, tagValue] of Object.entries(config.tags)) {
|
|
1044
|
+
const tagId = sha256(`${tagKey}:${tagValue}`);
|
|
1045
|
+
await tx.insert(tagsTable).values({
|
|
1046
|
+
id: tagId,
|
|
1047
|
+
name: tagKey,
|
|
1048
|
+
value: tagValue
|
|
1049
|
+
}).onConflictDoNothing().run();
|
|
1050
|
+
await tx.insert(evalsToTagsTable).values({
|
|
1051
|
+
evalId,
|
|
1052
|
+
tagId
|
|
1053
|
+
}).onConflictDoNothing().run();
|
|
1054
|
+
logger.debug(`Inserting tag ${tagId}`);
|
|
1055
|
+
}
|
|
1056
|
+
});
|
|
1057
|
+
invalidateEvaluationCache(evalId);
|
|
1058
|
+
return new Eval(config, {
|
|
1059
|
+
id: evalId,
|
|
1060
|
+
author,
|
|
1061
|
+
createdAt,
|
|
1062
|
+
persisted: true,
|
|
1063
|
+
runtimeOptions: sanitizeRuntimeOptions(opts?.runtimeOptions),
|
|
1064
|
+
durationMs: opts?.durationMs,
|
|
1065
|
+
generationDurationMs: opts?.generationDurationMs,
|
|
1066
|
+
evaluationDurationMs: opts?.evaluationDurationMs
|
|
1067
|
+
});
|
|
1068
|
+
}
|
|
1069
|
+
constructor(config, opts) {
|
|
1070
|
+
const createdAt = opts?.createdAt || /* @__PURE__ */ new Date();
|
|
1071
|
+
this.createdAt = createdAt.getTime();
|
|
1072
|
+
this.id = opts?.id || createEvalId(createdAt);
|
|
1073
|
+
this.author = opts?.author ?? null;
|
|
1074
|
+
this.config = config;
|
|
1075
|
+
this.results = [];
|
|
1076
|
+
this.prompts = opts?.prompts || [];
|
|
1077
|
+
this.datasetId = opts?.datasetId;
|
|
1078
|
+
this.persisted = opts?.persisted || false;
|
|
1079
|
+
this._resultsLoaded = false;
|
|
1080
|
+
this.vars = opts?.vars || [];
|
|
1081
|
+
this.runtimeOptions = opts?.runtimeOptions;
|
|
1082
|
+
this.durationMs = opts?.durationMs;
|
|
1083
|
+
this.generationDurationMs = opts?.generationDurationMs;
|
|
1084
|
+
this.evaluationDurationMs = opts?.evaluationDurationMs;
|
|
1085
|
+
}
|
|
1086
|
+
version() {
|
|
1087
|
+
/**
|
|
1088
|
+
* Version 3 is the denormalized version of where the table and results are stored on the eval object.
|
|
1089
|
+
* Version 4 is the normalized version where the results are stored in another database table and the table for visualization is generated by the app.
|
|
1090
|
+
*/
|
|
1091
|
+
return this.oldResults && "table" in this.oldResults ? 3 : 4;
|
|
1092
|
+
}
|
|
1093
|
+
useOldResults() {
|
|
1094
|
+
return this.version() < 4;
|
|
1095
|
+
}
|
|
1096
|
+
setTable(table) {
|
|
1097
|
+
invariant(this.version() < 4, "Eval is not version 3");
|
|
1098
|
+
invariant(this.oldResults, "Old results not found");
|
|
1099
|
+
this.oldResults.table = table;
|
|
1100
|
+
}
|
|
1101
|
+
async save() {
|
|
1102
|
+
const db = await getDb();
|
|
1103
|
+
const updateObj = {
|
|
1104
|
+
config: sanitizeTracingConfigForPersistence(this.config),
|
|
1105
|
+
isRedteam: this.config.redteam !== void 0,
|
|
1106
|
+
prompts: this.prompts,
|
|
1107
|
+
description: this.config.description,
|
|
1108
|
+
author: this.author,
|
|
1109
|
+
updatedAt: getCurrentTimestamp(),
|
|
1110
|
+
vars: Array.from(this.vars),
|
|
1111
|
+
runtimeOptions: sanitizeRuntimeOptions(this.runtimeOptions)
|
|
1112
|
+
};
|
|
1113
|
+
if (this.useOldResults()) {
|
|
1114
|
+
invariant(this.oldResults, "Old results not found");
|
|
1115
|
+
updateObj.results = this.oldResults;
|
|
1116
|
+
} else if (this.durationMs !== void 0 || this.generationDurationMs !== void 0 || this.evaluationDurationMs !== void 0) {
|
|
1117
|
+
let expr = sql`CASE WHEN json_valid(${evalsTable.results}) AND json_type(${evalsTable.results}) = 'object' THEN ${evalsTable.results} ELSE '{}' END`;
|
|
1118
|
+
if (this.durationMs !== void 0) expr = sql`json_set(${expr}, '$.durationMs', ${this.durationMs})`;
|
|
1119
|
+
if (this.generationDurationMs !== void 0) expr = sql`json_set(${expr}, '$.generationDurationMs', ${this.generationDurationMs})`;
|
|
1120
|
+
if (this.evaluationDurationMs !== void 0) expr = sql`json_set(${expr}, '$.evaluationDurationMs', ${this.evaluationDurationMs})`;
|
|
1121
|
+
updateObj.results = expr;
|
|
1122
|
+
}
|
|
1123
|
+
await db.update(evalsTable).set(updateObj).where(eq(evalsTable.id, this.id)).run();
|
|
1124
|
+
notifyEvaluationChanged(this.id);
|
|
1125
|
+
this.persisted = true;
|
|
1126
|
+
}
|
|
1127
|
+
setVars(vars) {
|
|
1128
|
+
this.vars = vars;
|
|
1129
|
+
}
|
|
1130
|
+
addVar(varName) {
|
|
1131
|
+
this.vars.push(varName);
|
|
1132
|
+
}
|
|
1133
|
+
/** Sets the evaluation phase duration and recomputes the total. Called by the evaluator. */
|
|
1134
|
+
setDurationMs(durationMs) {
|
|
1135
|
+
if (!Number.isFinite(durationMs) || durationMs < 0) return;
|
|
1136
|
+
this.evaluationDurationMs = durationMs;
|
|
1137
|
+
this.durationMs = (this.generationDurationMs ?? 0) + durationMs;
|
|
1138
|
+
}
|
|
1139
|
+
/** Sets the generation phase duration and recomputes the total. Called by doRedteamRun. */
|
|
1140
|
+
setGenerationDurationMs(durationMs) {
|
|
1141
|
+
if (!Number.isFinite(durationMs) || durationMs < 0) return;
|
|
1142
|
+
this.generationDurationMs = durationMs;
|
|
1143
|
+
this.durationMs = durationMs + (this.evaluationDurationMs ?? 0);
|
|
1144
|
+
}
|
|
1145
|
+
getPrompts() {
|
|
1146
|
+
if (this.useOldResults()) {
|
|
1147
|
+
invariant(this.oldResults, "Old results not found");
|
|
1148
|
+
return this.oldResults.table?.head.prompts || [];
|
|
1149
|
+
}
|
|
1150
|
+
return this.prompts;
|
|
1151
|
+
}
|
|
1152
|
+
async getTable() {
|
|
1153
|
+
if (this.useOldResults()) return this.oldResults?.table || {
|
|
1154
|
+
head: {
|
|
1155
|
+
prompts: [],
|
|
1156
|
+
vars: []
|
|
1157
|
+
},
|
|
1158
|
+
body: []
|
|
1159
|
+
};
|
|
1160
|
+
return convertResultsToTable(await this.toResultsFile());
|
|
1161
|
+
}
|
|
1162
|
+
async addResult(result) {
|
|
1163
|
+
if (result.repeatGroupId !== void 0) this.observedRepeatedResults = true;
|
|
1164
|
+
const httpStatus = result.response?.metadata?.http?.status;
|
|
1165
|
+
if (this.observedTargetErrorStatus === void 0 && typeof httpStatus === "number" && isNonTransientHttpStatus(httpStatus)) this.observedTargetErrorStatus = httpStatus;
|
|
1166
|
+
const newResult = await EvalResult.createFromEvaluateResult(this.id, result, { persist: this.persisted });
|
|
1167
|
+
if (!this.persisted) this.results.push(newResult);
|
|
1168
|
+
if (this.persisted) notifyEvaluationChanged(this.id);
|
|
1169
|
+
}
|
|
1170
|
+
recordFinalJsonlResult(result) {
|
|
1171
|
+
this.finalJsonlResults.set(getResultIndexKey(result), result);
|
|
1172
|
+
if (result.repeatGroupId !== void 0) this.observedRepeatedResults = true;
|
|
1173
|
+
}
|
|
1174
|
+
getFinalJsonlResults() {
|
|
1175
|
+
return Array.from(this.finalJsonlResults.values());
|
|
1176
|
+
}
|
|
1177
|
+
async getObservedRepeatStability() {
|
|
1178
|
+
return this.observedRepeatedResults ? this.getRepeatStability() : void 0;
|
|
1179
|
+
}
|
|
1180
|
+
recordResultPersistenceFailure(result) {
|
|
1181
|
+
this.resultPersistenceFailed = true;
|
|
1182
|
+
const key = getResultIndexKey(result);
|
|
1183
|
+
this.failedResults.set(key, result);
|
|
1184
|
+
this.failedEvalResults.delete(key);
|
|
1185
|
+
}
|
|
1186
|
+
hasResultPersistenceFailure(result) {
|
|
1187
|
+
return this.failedResults.has(getResultIndexKey(result));
|
|
1188
|
+
}
|
|
1189
|
+
async getFailedResultsByTestIdx(testIdx) {
|
|
1190
|
+
const reconstructed = [];
|
|
1191
|
+
for (const [key, row] of this.failedResults) {
|
|
1192
|
+
if (row.testIdx !== testIdx) continue;
|
|
1193
|
+
let evalResult = this.failedEvalResults.get(key);
|
|
1194
|
+
if (!evalResult) {
|
|
1195
|
+
evalResult = await EvalResult.createFromEvaluateResult(this.id, row, { persist: false });
|
|
1196
|
+
this.failedEvalResults.set(key, evalResult);
|
|
1197
|
+
}
|
|
1198
|
+
reconstructed.push(evalResult);
|
|
1199
|
+
}
|
|
1200
|
+
return reconstructed;
|
|
1201
|
+
}
|
|
1202
|
+
async *fetchResultsBatched(batchSize = 100) {
|
|
1203
|
+
if (!this.persisted) {
|
|
1204
|
+
for (let offset = 0; offset < this.results.length; offset += batchSize) yield this.results.slice(offset, offset + batchSize);
|
|
1205
|
+
return;
|
|
1206
|
+
}
|
|
1207
|
+
for await (const batch of EvalResult.findManyByEvalIdBatched(this.id, { batchSize })) yield batch;
|
|
1208
|
+
}
|
|
1209
|
+
async getResultsCount() {
|
|
1210
|
+
return getCachedResultsCount(this.id);
|
|
1211
|
+
}
|
|
1212
|
+
/**
|
|
1213
|
+
* Get the total count of all result rows for this eval.
|
|
1214
|
+
* Use this when iterating over all results (e.g., for sharing progress).
|
|
1215
|
+
* This may be higher than getResultsCount() when there are multiple prompts/providers.
|
|
1216
|
+
*/
|
|
1217
|
+
async getTotalResultRowCount() {
|
|
1218
|
+
return getTotalResultRowCount(this.id);
|
|
1219
|
+
}
|
|
1220
|
+
/**
|
|
1221
|
+
* Find a non-transient HTTP error status from evaluation results.
|
|
1222
|
+
* Returns the first non-transient status (401, 403, 404, 500, 501) found, or undefined.
|
|
1223
|
+
*
|
|
1224
|
+
* For persisted evals: Uses efficient O(1) database query with LIMIT 1, and also scans
|
|
1225
|
+
* the rows that could not be saved, which the database does not have.
|
|
1226
|
+
* For non-persisted evals: Falls back to scanning in-memory results.
|
|
1227
|
+
*/
|
|
1228
|
+
async findTargetErrorStatus() {
|
|
1229
|
+
const scan = (results) => {
|
|
1230
|
+
for (const result of results) {
|
|
1231
|
+
const status = result.response?.metadata?.http?.status;
|
|
1232
|
+
if (typeof status === "number" && isNonTransientHttpStatus(status)) return status;
|
|
1233
|
+
}
|
|
1234
|
+
};
|
|
1235
|
+
const scanInMemory = () => scan(this.results);
|
|
1236
|
+
if (!this.persisted) return scanInMemory();
|
|
1237
|
+
const unsavedStatus = scan(this.failedResults.values());
|
|
1238
|
+
try {
|
|
1239
|
+
return (await (await getDb()).select({ httpStatus: sql`CAST(json_extract(${evalResultsTable.response}, '$.metadata.http.status') AS INTEGER)` }).from(evalResultsTable).where(and(eq(evalResultsTable.evalId, this.id), sql`json_extract(${evalResultsTable.response}, '$.metadata.http.status') IN (${sql.join(NON_TRANSIENT_HTTP_STATUSES.map((s) => sql`${s}`), sql`, `)})`)).limit(1).get())?.httpStatus ?? unsavedStatus;
|
|
1240
|
+
} catch {
|
|
1241
|
+
return scanInMemory() ?? unsavedStatus ?? this.observedTargetErrorStatus;
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
async fetchResultsByTestIdx(testIdx) {
|
|
1245
|
+
return await EvalResult.findManyByEvalId(this.id, { testIdx });
|
|
1246
|
+
}
|
|
1247
|
+
/**
|
|
1248
|
+
* CRITICAL: Builds the WHERE SQL clause for filtering results.
|
|
1249
|
+
* This is the single source of truth for all filtering logic.
|
|
1250
|
+
* Used by both queryTestIndices() (pagination) and getFilteredMetrics().
|
|
1251
|
+
*
|
|
1252
|
+
* SECURITY: This method uses Drizzle's sql template strings for parameterized queries
|
|
1253
|
+
* to prevent SQL injection. All user-provided values are passed as parameters,
|
|
1254
|
+
* not interpolated into the SQL string.
|
|
1255
|
+
*
|
|
1256
|
+
* Any changes to filter logic MUST be made here to ensure consistency
|
|
1257
|
+
* between displayed rows and calculated metrics.
|
|
1258
|
+
*
|
|
1259
|
+
* @returns SQL fragment (without "WHERE" keyword) that can be used in queries
|
|
1260
|
+
*/
|
|
1261
|
+
buildFilterWhereSql(opts) {
|
|
1262
|
+
const mode = opts.filterMode ?? "all";
|
|
1263
|
+
const conditions = [sql`eval_id = ${this.id}`];
|
|
1264
|
+
if (mode === "errors") conditions.push(sql`failure_reason = ${ResultFailureReason.ERROR}`);
|
|
1265
|
+
else if (mode === "failures") conditions.push(sql`success = 0 AND failure_reason != ${ResultFailureReason.ERROR}`);
|
|
1266
|
+
else if (mode === "passes") conditions.push(sql`success = 1`);
|
|
1267
|
+
else if (mode === "highlights") conditions.push(sql`json_extract(grading_result, '$.comment') LIKE ${"!highlight%"}`);
|
|
1268
|
+
else if (mode === "user-rated") conditions.push(sql`
|
|
1269
|
+
EXISTS (
|
|
1270
|
+
SELECT 1
|
|
1271
|
+
FROM json_each(grading_result, '$.componentResults')
|
|
1272
|
+
WHERE json_extract(value, '$.assertion.type') = ${HUMAN_ASSERTION_TYPE}
|
|
1273
|
+
)
|
|
1274
|
+
`);
|
|
1275
|
+
if (opts.filters && opts.filters.length > 0) {
|
|
1276
|
+
const filterConditions = [];
|
|
1277
|
+
opts.filters.forEach((filter) => {
|
|
1278
|
+
let parsedFilter;
|
|
1279
|
+
try {
|
|
1280
|
+
parsedFilter = JSON.parse(filter);
|
|
1281
|
+
} catch {
|
|
1282
|
+
logger.warn("Ignoring malformed eval filter JSON");
|
|
1283
|
+
return;
|
|
1284
|
+
}
|
|
1285
|
+
if (!parsedFilter || typeof parsedFilter !== "object" || Array.isArray(parsedFilter)) {
|
|
1286
|
+
logger.warn("Ignoring invalid eval filter");
|
|
1287
|
+
return;
|
|
1288
|
+
}
|
|
1289
|
+
const { logicOperator, type, operator, value, field } = parsedFilter;
|
|
1290
|
+
if (typeof type !== "string" || typeof operator !== "string" || logicOperator !== void 0 && typeof logicOperator !== "string" || field !== void 0 && typeof field !== "string" || value !== void 0 && typeof value !== "string" && typeof value !== "number") {
|
|
1291
|
+
logger.warn("Ignoring invalid eval filter fields");
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
let condition = null;
|
|
1295
|
+
if (type === "metric") {
|
|
1296
|
+
const metricKey = field || value;
|
|
1297
|
+
if (!metricKey) {
|
|
1298
|
+
logger.warn("Invalid metric filter: missing field and value", { filter });
|
|
1299
|
+
return;
|
|
1300
|
+
}
|
|
1301
|
+
const numericValue = typeof value === "number" ? value : Number.parseFloat(String(value));
|
|
1302
|
+
if (operator === "is_defined" || operator === "equals" && !field) condition = sql`EXISTS (
|
|
1303
|
+
SELECT 1
|
|
1304
|
+
FROM json_each(named_scores)
|
|
1305
|
+
WHERE json_each.key = ${metricKey}
|
|
1306
|
+
)`;
|
|
1307
|
+
else if (Number.isFinite(numericValue)) {
|
|
1308
|
+
if (operator === "eq") condition = sql`EXISTS (
|
|
1309
|
+
SELECT 1
|
|
1310
|
+
FROM json_each(named_scores)
|
|
1311
|
+
WHERE json_each.key = ${metricKey}
|
|
1312
|
+
AND CAST(json_each.value AS REAL) = ${numericValue}
|
|
1313
|
+
)`;
|
|
1314
|
+
else if (operator === "neq") condition = sql`EXISTS (
|
|
1315
|
+
SELECT 1
|
|
1316
|
+
FROM json_each(named_scores)
|
|
1317
|
+
WHERE json_each.key = ${metricKey}
|
|
1318
|
+
AND CAST(json_each.value AS REAL) != ${numericValue}
|
|
1319
|
+
)`;
|
|
1320
|
+
else if (operator === "gt") condition = sql`EXISTS (
|
|
1321
|
+
SELECT 1
|
|
1322
|
+
FROM json_each(named_scores)
|
|
1323
|
+
WHERE json_each.key = ${metricKey}
|
|
1324
|
+
AND CAST(json_each.value AS REAL) > ${numericValue}
|
|
1325
|
+
)`;
|
|
1326
|
+
else if (operator === "gte") condition = sql`EXISTS (
|
|
1327
|
+
SELECT 1
|
|
1328
|
+
FROM json_each(named_scores)
|
|
1329
|
+
WHERE json_each.key = ${metricKey}
|
|
1330
|
+
AND CAST(json_each.value AS REAL) >= ${numericValue}
|
|
1331
|
+
)`;
|
|
1332
|
+
else if (operator === "lt") condition = sql`EXISTS (
|
|
1333
|
+
SELECT 1
|
|
1334
|
+
FROM json_each(named_scores)
|
|
1335
|
+
WHERE json_each.key = ${metricKey}
|
|
1336
|
+
AND CAST(json_each.value AS REAL) < ${numericValue}
|
|
1337
|
+
)`;
|
|
1338
|
+
else if (operator === "lte") condition = sql`EXISTS (
|
|
1339
|
+
SELECT 1
|
|
1340
|
+
FROM json_each(named_scores)
|
|
1341
|
+
WHERE json_each.key = ${metricKey}
|
|
1342
|
+
AND CAST(json_each.value AS REAL) <= ${numericValue}
|
|
1343
|
+
)`;
|
|
1344
|
+
} else {
|
|
1345
|
+
logger.warn("Invalid numeric value in metric filter", {
|
|
1346
|
+
metricKey,
|
|
1347
|
+
value,
|
|
1348
|
+
numericValue,
|
|
1349
|
+
operator
|
|
1350
|
+
});
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1353
|
+
} else if (type === "metadata" && field) {
|
|
1354
|
+
if (operator === "equals") condition = sql`EXISTS (
|
|
1355
|
+
SELECT 1
|
|
1356
|
+
FROM json_each(metadata)
|
|
1357
|
+
WHERE json_each.key = ${field}
|
|
1358
|
+
AND json_each.value = ${value}
|
|
1359
|
+
)`;
|
|
1360
|
+
else if (operator === "contains") condition = sql`EXISTS (
|
|
1361
|
+
SELECT 1
|
|
1362
|
+
FROM json_each(metadata)
|
|
1363
|
+
WHERE json_each.key = ${field}
|
|
1364
|
+
AND json_each.value LIKE ${`%${value}%`}
|
|
1365
|
+
)`;
|
|
1366
|
+
else if (operator === "not_contains") condition = sql`NOT EXISTS (
|
|
1367
|
+
SELECT 1
|
|
1368
|
+
FROM json_each(metadata)
|
|
1369
|
+
WHERE json_each.key = ${field}
|
|
1370
|
+
AND json_each.value LIKE ${`%${value}%`}
|
|
1371
|
+
)`;
|
|
1372
|
+
else if (operator === "exists") condition = sql`EXISTS (
|
|
1373
|
+
SELECT 1
|
|
1374
|
+
FROM json_each(metadata)
|
|
1375
|
+
WHERE json_each.key = ${field}
|
|
1376
|
+
AND LENGTH(TRIM(COALESCE(json_each.value, ''))) > 0
|
|
1377
|
+
)`;
|
|
1378
|
+
} else if (type === "plugin" && typeof value === "string") {
|
|
1379
|
+
const isCategory = Object.keys(PLUGIN_CATEGORIES).includes(value);
|
|
1380
|
+
if (operator === "equals") {
|
|
1381
|
+
if (isCategory) condition = sql`json_extract(metadata, '$.pluginId') LIKE ${`${value}:%`}`;
|
|
1382
|
+
else condition = sql`json_extract(metadata, '$.pluginId') = ${value}`;
|
|
1383
|
+
} else if (operator === "not_equals") {
|
|
1384
|
+
if (isCategory) condition = sql`(json_extract(metadata, '$.pluginId') IS NULL OR (json_extract(metadata, '$.pluginId') != ${value} AND json_extract(metadata, '$.pluginId') NOT LIKE ${`${value}:%`}))`;
|
|
1385
|
+
else condition = sql`(json_extract(metadata, '$.pluginId') IS NULL OR json_extract(metadata, '$.pluginId') != ${value})`;
|
|
1386
|
+
}
|
|
1387
|
+
} else if (type === "strategy" && operator === "equals") {
|
|
1388
|
+
if (value === "basic") condition = sql`(json_extract(metadata, '$.strategyId') IS NULL OR json_extract(metadata, '$.strategyId') = '')`;
|
|
1389
|
+
else condition = sql`json_extract(metadata, '$.strategyId') = ${value}`;
|
|
1390
|
+
} else if (type === "severity" && operator === "equals") {
|
|
1391
|
+
const explicit = sql`json_extract(metadata, '$.severity') = ${value}`;
|
|
1392
|
+
const severityMap = getRiskCategorySeverityMap(this.config?.redteam?.plugins);
|
|
1393
|
+
const pluginConditions = Object.entries(severityMap).filter(([, severity]) => severity === value).map(([pluginId]) => pluginId).map((pluginId) => {
|
|
1394
|
+
return pluginId.includes(":") ? sql`json_extract(metadata, '$.pluginId') = ${pluginId}` : sql`json_extract(metadata, '$.pluginId') LIKE ${`${pluginId}:%`}`;
|
|
1395
|
+
});
|
|
1396
|
+
if (pluginConditions.length > 0) {
|
|
1397
|
+
const pluginMatch = sql.join(pluginConditions, sql` OR `);
|
|
1398
|
+
const overrideOk = sql`(json_extract(metadata, '$.severity') IS NULL OR json_extract(metadata, '$.severity') = ${value})`;
|
|
1399
|
+
condition = sql`(${explicit} OR ((${pluginMatch}) AND ${overrideOk}))`;
|
|
1400
|
+
} else condition = sql`(${explicit})`;
|
|
1401
|
+
} else if (type === "policy" && operator === "equals") condition = sql`(named_scores LIKE '%PolicyViolation:%' AND named_scores LIKE ${`%${value}%`})`;
|
|
1402
|
+
if (condition) filterConditions.push({
|
|
1403
|
+
condition,
|
|
1404
|
+
logicOperator: logicOperator || "AND"
|
|
1405
|
+
});
|
|
1406
|
+
});
|
|
1407
|
+
const filterClause = combineFilterConditions(filterConditions);
|
|
1408
|
+
if (filterClause) conditions.push(sql`(${filterClause})`);
|
|
1409
|
+
}
|
|
1410
|
+
if (opts.searchQuery && opts.searchQuery.trim() !== "") {
|
|
1411
|
+
const searchPattern = `%${opts.searchQuery}%`;
|
|
1412
|
+
const searchConditions = [
|
|
1413
|
+
sql`response LIKE ${searchPattern}`,
|
|
1414
|
+
sql`json_extract(grading_result, '$.reason') LIKE ${searchPattern}`,
|
|
1415
|
+
sql`json_extract(grading_result, '$.comment') LIKE ${searchPattern}`,
|
|
1416
|
+
sql`json_extract(named_scores, '$') LIKE ${searchPattern}`,
|
|
1417
|
+
sql`json_remove(metadata, ${`$.${PROMPTFOO_METADATA_KEY}`}) LIKE ${searchPattern}`,
|
|
1418
|
+
sql`json_extract(test_case, '$.vars') LIKE ${searchPattern}`,
|
|
1419
|
+
sql`json_extract(test_case, '$.metadata') LIKE ${searchPattern}`
|
|
1420
|
+
];
|
|
1421
|
+
const searchClause = sql.join(searchConditions, sql` OR `);
|
|
1422
|
+
conditions.push(sql`(${searchClause})`);
|
|
1423
|
+
}
|
|
1424
|
+
return sql.join(conditions, sql` AND `);
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Private helper method to build filter conditions and query for test indices.
|
|
1428
|
+
*
|
|
1429
|
+
* SECURITY: Uses parameterized queries via Drizzle's sql template strings
|
|
1430
|
+
* to prevent SQL injection attacks.
|
|
1431
|
+
*/
|
|
1432
|
+
async queryTestIndices(opts) {
|
|
1433
|
+
const db = await getDb();
|
|
1434
|
+
const offset = opts.offset ?? 0;
|
|
1435
|
+
const limit = opts.limit ?? 50;
|
|
1436
|
+
const whereSql = this.buildFilterWhereSql({
|
|
1437
|
+
filterMode: opts.filterMode,
|
|
1438
|
+
searchQuery: opts.searchQuery,
|
|
1439
|
+
filters: opts.filters
|
|
1440
|
+
});
|
|
1441
|
+
const filteredCountQuery = sql`
|
|
1442
|
+
SELECT COUNT(DISTINCT test_idx) as count
|
|
1443
|
+
FROM eval_results
|
|
1444
|
+
WHERE ${whereSql}
|
|
1445
|
+
`;
|
|
1446
|
+
const countStart = Date.now();
|
|
1447
|
+
const countResult = await db.get(filteredCountQuery);
|
|
1448
|
+
const countEnd = Date.now();
|
|
1449
|
+
logger.debug(`Count query took ${countEnd - countStart}ms`);
|
|
1450
|
+
const filteredCount = countResult?.count || 0;
|
|
1451
|
+
const idxQuery = sql`
|
|
1452
|
+
SELECT DISTINCT test_idx
|
|
1453
|
+
FROM eval_results
|
|
1454
|
+
WHERE ${whereSql}
|
|
1455
|
+
ORDER BY test_idx
|
|
1456
|
+
LIMIT ${limit}
|
|
1457
|
+
OFFSET ${offset}
|
|
1458
|
+
`;
|
|
1459
|
+
const idxStart = Date.now();
|
|
1460
|
+
const rows = await db.all(idxQuery);
|
|
1461
|
+
const idxEnd = Date.now();
|
|
1462
|
+
logger.debug(`Index query took ${idxEnd - idxStart}ms`);
|
|
1463
|
+
return {
|
|
1464
|
+
testIndices: rows.map((row) => row.test_idx),
|
|
1465
|
+
filteredCount
|
|
1466
|
+
};
|
|
1467
|
+
}
|
|
1468
|
+
/**
|
|
1469
|
+
* CRITICAL: Calculates metrics for filtered results.
|
|
1470
|
+
* Uses the SAME WHERE clause as queryTestIndices() to ensure consistency.
|
|
1471
|
+
*
|
|
1472
|
+
* SECURITY: Uses parameterized SQL queries to prevent SQL injection.
|
|
1473
|
+
*
|
|
1474
|
+
* This method is called from the API route when filters are active to provide
|
|
1475
|
+
* metrics that accurately reflect the filtered dataset.
|
|
1476
|
+
*
|
|
1477
|
+
* @returns Array of PromptMetrics, one per prompt
|
|
1478
|
+
*/
|
|
1479
|
+
async getFilteredMetrics(opts) {
|
|
1480
|
+
const whereSql = this.buildFilterWhereSql(opts);
|
|
1481
|
+
return calculateFilteredMetrics({
|
|
1482
|
+
evalId: this.id,
|
|
1483
|
+
numPrompts: this.prompts.length,
|
|
1484
|
+
whereSql
|
|
1485
|
+
});
|
|
1486
|
+
}
|
|
1487
|
+
async getTablePage(opts) {
|
|
1488
|
+
const totalCount = await this.getResultsCount();
|
|
1489
|
+
let testIndices;
|
|
1490
|
+
let filteredCount;
|
|
1491
|
+
if (opts.testIndices && opts.testIndices.length > 0) {
|
|
1492
|
+
testIndices = opts.testIndices;
|
|
1493
|
+
filteredCount = testIndices.length;
|
|
1494
|
+
} else {
|
|
1495
|
+
const hasComplexFilters = opts.filters && opts.filters.length > 0;
|
|
1496
|
+
let queryResult;
|
|
1497
|
+
if (hasComplexFilters) {
|
|
1498
|
+
logger.debug("Using original query for complex filters");
|
|
1499
|
+
queryResult = await this.queryTestIndices({
|
|
1500
|
+
offset: opts.offset,
|
|
1501
|
+
limit: opts.limit,
|
|
1502
|
+
filterMode: opts.filterMode,
|
|
1503
|
+
searchQuery: opts.searchQuery,
|
|
1504
|
+
filters: opts.filters
|
|
1505
|
+
});
|
|
1506
|
+
} else {
|
|
1507
|
+
logger.debug("Using optimized query for table page");
|
|
1508
|
+
queryResult = await queryTestIndicesOptimized(this.id, {
|
|
1509
|
+
offset: opts.offset,
|
|
1510
|
+
limit: opts.limit,
|
|
1511
|
+
filterMode: opts.filterMode,
|
|
1512
|
+
searchQuery: opts.searchQuery,
|
|
1513
|
+
filters: opts.filters
|
|
1514
|
+
});
|
|
1515
|
+
}
|
|
1516
|
+
testIndices = queryResult.testIndices;
|
|
1517
|
+
filteredCount = queryResult.filteredCount;
|
|
1518
|
+
}
|
|
1519
|
+
const varsStart = Date.now();
|
|
1520
|
+
const vars = Array.from(this.vars);
|
|
1521
|
+
const varsEnd = Date.now();
|
|
1522
|
+
logger.debug(`Vars query took ${varsEnd - varsStart}ms`);
|
|
1523
|
+
const body = [];
|
|
1524
|
+
const bodyStart = Date.now();
|
|
1525
|
+
if (testIndices.length === 0) {
|
|
1526
|
+
const bodyEnd = Date.now();
|
|
1527
|
+
logger.debug(`Body query took ${bodyEnd - bodyStart}ms`);
|
|
1528
|
+
return {
|
|
1529
|
+
head: {
|
|
1530
|
+
prompts: this.prompts,
|
|
1531
|
+
vars
|
|
1532
|
+
},
|
|
1533
|
+
body,
|
|
1534
|
+
totalCount,
|
|
1535
|
+
filteredCount,
|
|
1536
|
+
id: this.id
|
|
1537
|
+
};
|
|
1538
|
+
}
|
|
1539
|
+
const allResults = await EvalResult.findManyByEvalIdAndTestIndices(this.id, testIndices);
|
|
1540
|
+
if (allResults.some((result) => {
|
|
1541
|
+
const hasSessionIds = Array.isArray(result.metadata?.sessionIds) && result.metadata.sessionIds.length > 0;
|
|
1542
|
+
const hasSessionId = Boolean(result.metadata?.sessionId);
|
|
1543
|
+
const notInVars = !result.testCase?.vars?.sessionId;
|
|
1544
|
+
return (hasSessionIds || hasSessionId) && notInVars;
|
|
1545
|
+
}) && !vars.includes("sessionId")) vars.push("sessionId");
|
|
1546
|
+
const resultsByTestIdx = /* @__PURE__ */ new Map();
|
|
1547
|
+
for (const result of allResults) {
|
|
1548
|
+
if (!resultsByTestIdx.has(result.testIdx)) resultsByTestIdx.set(result.testIdx, []);
|
|
1549
|
+
resultsByTestIdx.get(result.testIdx).push(result);
|
|
1550
|
+
}
|
|
1551
|
+
for (const testIdx of testIndices) {
|
|
1552
|
+
const results = resultsByTestIdx.get(testIdx) || [];
|
|
1553
|
+
if (results.length > 0) body.push(convertTestResultsToTableRow(results, vars));
|
|
1554
|
+
}
|
|
1555
|
+
const bodyEnd = Date.now();
|
|
1556
|
+
logger.debug(`Body query took ${bodyEnd - bodyStart}ms`);
|
|
1557
|
+
return {
|
|
1558
|
+
head: {
|
|
1559
|
+
prompts: this.prompts,
|
|
1560
|
+
vars
|
|
1561
|
+
},
|
|
1562
|
+
body,
|
|
1563
|
+
totalCount,
|
|
1564
|
+
filteredCount,
|
|
1565
|
+
id: this.id
|
|
1566
|
+
};
|
|
1567
|
+
}
|
|
1568
|
+
async addPrompts(prompts) {
|
|
1569
|
+
this.prompts = prompts;
|
|
1570
|
+
if (this.persisted) {
|
|
1571
|
+
await (await getDb()).update(evalsTable).set({ prompts }).where(eq(evalsTable.id, this.id)).run();
|
|
1572
|
+
notifyEvaluationChanged(this.id);
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
async setResults(results) {
|
|
1576
|
+
if (this.persisted && results.length > 0) {
|
|
1577
|
+
await (await getDb()).insert(evalResultsTable).values(results.map((r) => ({
|
|
1578
|
+
...r,
|
|
1579
|
+
metadata: persistTraceMetadata(persistRepeatMetadata(r.metadata, r.repeatIndex, r.repeatGroupId), r.traceId, r.evaluationId),
|
|
1580
|
+
evalId: this.id
|
|
1581
|
+
}))).run();
|
|
1582
|
+
notifyEvaluationChanged(this.id);
|
|
1583
|
+
}
|
|
1584
|
+
if (this.persisted) this.clearResults();
|
|
1585
|
+
else {
|
|
1586
|
+
this.results = results;
|
|
1587
|
+
this._resultsLoaded = true;
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
async loadResults() {
|
|
1591
|
+
if (this.persisted) this.results = await EvalResult.findManyByEvalId(this.id);
|
|
1592
|
+
this._resultsLoaded = true;
|
|
1593
|
+
}
|
|
1594
|
+
async getResults() {
|
|
1595
|
+
if (this.useOldResults()) {
|
|
1596
|
+
invariant(this.oldResults, "Old results not found");
|
|
1597
|
+
return this.oldResults.results;
|
|
1598
|
+
}
|
|
1599
|
+
await this.loadResults();
|
|
1600
|
+
this._resultsLoaded = true;
|
|
1601
|
+
return this.results;
|
|
1602
|
+
}
|
|
1603
|
+
clearResults() {
|
|
1604
|
+
this.results = [];
|
|
1605
|
+
this._resultsLoaded = false;
|
|
1606
|
+
}
|
|
1607
|
+
getStats() {
|
|
1608
|
+
const stats = {
|
|
1609
|
+
successes: 0,
|
|
1610
|
+
failures: 0,
|
|
1611
|
+
errors: 0,
|
|
1612
|
+
tokenUsage: createEmptyTokenUsage(),
|
|
1613
|
+
durationMs: this.durationMs,
|
|
1614
|
+
generationDurationMs: this.generationDurationMs,
|
|
1615
|
+
evaluationDurationMs: this.evaluationDurationMs
|
|
1616
|
+
};
|
|
1617
|
+
for (const prompt of this.prompts) {
|
|
1618
|
+
stats.successes += prompt.metrics?.testPassCount ?? 0;
|
|
1619
|
+
stats.failures += prompt.metrics?.testFailCount ?? 0;
|
|
1620
|
+
stats.errors += prompt.metrics?.testErrorCount ?? 0;
|
|
1621
|
+
if (prompt.metrics?.testCacheHitCount) stats.cacheHits = (stats.cacheHits ?? 0) + prompt.metrics.testCacheHitCount;
|
|
1622
|
+
accumulateTokenUsage(stats.tokenUsage, prompt.metrics?.tokenUsage);
|
|
1623
|
+
}
|
|
1624
|
+
accumulateGenerationTokenUsage(stats.tokenUsage, this.config.metadata?.generationAccounting?.tokenUsage);
|
|
1625
|
+
return stats;
|
|
1626
|
+
}
|
|
1627
|
+
async getRepeatStability() {
|
|
1628
|
+
if (this.useOldResults()) return calculateRepeatStability(this.oldResults?.results ?? []);
|
|
1629
|
+
const calculator = new RepeatStabilityCalculator();
|
|
1630
|
+
const recovered = new Map(this.failedResults);
|
|
1631
|
+
for (const [key, result] of this.failedEvalResults) recovered.set(key, result);
|
|
1632
|
+
for (const [key, result] of this.finalJsonlResults) recovered.set(key, result);
|
|
1633
|
+
for await (const batch of this.fetchResultsBatched()) for (const result of batch) {
|
|
1634
|
+
const key = getResultIndexKey(result);
|
|
1635
|
+
calculator.addResult(recovered.get(key) ?? result);
|
|
1636
|
+
recovered.delete(key);
|
|
1637
|
+
}
|
|
1638
|
+
calculator.addResults(recovered.values());
|
|
1639
|
+
return calculator.getSummary();
|
|
1640
|
+
}
|
|
1641
|
+
async toEvaluateSummary() {
|
|
1642
|
+
if (this.useOldResults()) {
|
|
1643
|
+
invariant(this.oldResults, "Old results not found");
|
|
1644
|
+
return {
|
|
1645
|
+
version: 2,
|
|
1646
|
+
timestamp: new Date(this.createdAt).toISOString(),
|
|
1647
|
+
results: this.oldResults.results,
|
|
1648
|
+
table: this.oldResults.table,
|
|
1649
|
+
stats: this.oldResults.stats
|
|
1650
|
+
};
|
|
1651
|
+
}
|
|
1652
|
+
if (this.results.length === 0) await this.loadResults();
|
|
1653
|
+
const stats = await this.getStats();
|
|
1654
|
+
const stripFlags = getStripFlags(this.config.env);
|
|
1655
|
+
const prompts = this.prompts.map((p) => projectPrompt(p, stripFlags.shouldStripPromptText));
|
|
1656
|
+
const calculator = new RepeatStabilityCalculator();
|
|
1657
|
+
const results = this.results.map((result) => {
|
|
1658
|
+
const exported = result.toEvaluateResult(stripFlags);
|
|
1659
|
+
calculator.addResult({
|
|
1660
|
+
...exported,
|
|
1661
|
+
gradingResult: result.gradingResult
|
|
1662
|
+
});
|
|
1663
|
+
return exported;
|
|
1664
|
+
});
|
|
1665
|
+
const repeatStability = calculator.getSummary();
|
|
1666
|
+
return {
|
|
1667
|
+
version: 3,
|
|
1668
|
+
timestamp: new Date(this.createdAt).toISOString(),
|
|
1669
|
+
prompts,
|
|
1670
|
+
results,
|
|
1671
|
+
stats,
|
|
1672
|
+
...repeatStability && { repeatStability }
|
|
1673
|
+
};
|
|
1674
|
+
}
|
|
1675
|
+
async getTraces() {
|
|
1676
|
+
try {
|
|
1677
|
+
return (await getTraceStore().getTracesByEvaluation(this.id)).map((trace) => ({
|
|
1678
|
+
traceId: trace.traceId,
|
|
1679
|
+
evaluationId: trace.evaluationId,
|
|
1680
|
+
testCaseId: trace.testCaseId,
|
|
1681
|
+
metadata: trace.metadata,
|
|
1682
|
+
spans: (trace.spans || []).map((span) => {
|
|
1683
|
+
const durationMs = span.endTime && span.startTime ? (span.endTime - span.startTime) / 1e6 : void 0;
|
|
1684
|
+
const statusCode = span.statusCode === 1 ? "ok" : span.statusCode === 2 ? "error" : "unset";
|
|
1685
|
+
return {
|
|
1686
|
+
spanId: span.spanId,
|
|
1687
|
+
parentSpanId: span.parentSpanId,
|
|
1688
|
+
name: span.name,
|
|
1689
|
+
kind: span.kind || "unspecified",
|
|
1690
|
+
startTime: span.startTime,
|
|
1691
|
+
endTime: span.endTime,
|
|
1692
|
+
durationMs,
|
|
1693
|
+
attributes: span.attributes || {},
|
|
1694
|
+
status: {
|
|
1695
|
+
code: statusCode,
|
|
1696
|
+
message: span.statusMessage
|
|
1697
|
+
},
|
|
1698
|
+
depth: 0,
|
|
1699
|
+
events: span.events || []
|
|
1700
|
+
};
|
|
1701
|
+
})
|
|
1702
|
+
}));
|
|
1703
|
+
} catch (error) {
|
|
1704
|
+
logger.debug(`Failed to fetch traces for eval ${this.id}: ${error}`);
|
|
1705
|
+
return [];
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
async toResultsFile() {
|
|
1709
|
+
const traces = await this.getTraces();
|
|
1710
|
+
const stripFlags = getStripFlags(this.config.env);
|
|
1711
|
+
return {
|
|
1712
|
+
version: this.version(),
|
|
1713
|
+
createdAt: new Date(this.createdAt).toISOString(),
|
|
1714
|
+
results: await this.toEvaluateSummary(),
|
|
1715
|
+
config: sanitizeConfigForOutput(this.config, stripFlags),
|
|
1716
|
+
author: this.author || null,
|
|
1717
|
+
prompts: this.getPrompts().map((prompt) => projectPrompt(prompt, stripFlags.shouldStripPromptText)),
|
|
1718
|
+
...this.vars.length > 0 && { vars: [...this.vars] },
|
|
1719
|
+
datasetId: this.datasetId || null,
|
|
1720
|
+
...traces.length > 0 && { traces: projectTracesForOutput(traces, stripFlags) }
|
|
1721
|
+
};
|
|
1722
|
+
}
|
|
1723
|
+
async delete({ notify = true } = {}) {
|
|
1724
|
+
await (await getDb()).transaction(async (tx) => {
|
|
1725
|
+
await deleteTraceRecordsForEvals(tx, [this.id]);
|
|
1726
|
+
await tx.delete(evalsToDatasetsTable).where(eq(evalsToDatasetsTable.evalId, this.id)).run();
|
|
1727
|
+
await tx.delete(evalsToPromptsTable).where(eq(evalsToPromptsTable.evalId, this.id)).run();
|
|
1728
|
+
await tx.delete(evalsToTagsTable).where(eq(evalsToTagsTable.evalId, this.id)).run();
|
|
1729
|
+
await tx.delete(evalResultsTable).where(eq(evalResultsTable.evalId, this.id)).run();
|
|
1730
|
+
await tx.delete(evalsTable).where(eq(evalsTable.id, this.id)).run();
|
|
1731
|
+
});
|
|
1732
|
+
if (notify) notifyEvaluationsDeleted([this.id]);
|
|
1733
|
+
}
|
|
1734
|
+
/**
|
|
1735
|
+
* Creates a deep copy of this eval including all results.
|
|
1736
|
+
* Uses batching to avoid memory exhaustion on large evals.
|
|
1737
|
+
* @param description - Optional description for the new eval
|
|
1738
|
+
* @param distinctTestCount - Optional pre-computed test count to avoid duplicate query
|
|
1739
|
+
*/
|
|
1740
|
+
async copy(description, distinctTestCount) {
|
|
1741
|
+
const newEvalId = createEvalId(/* @__PURE__ */ new Date());
|
|
1742
|
+
const copyDescription = description || `${this.description || "Evaluation"} (Copy)`;
|
|
1743
|
+
const testCount = distinctTestCount ?? await this.getResultsCount();
|
|
1744
|
+
logger.info("Starting eval copy", {
|
|
1745
|
+
sourceEvalId: this.id,
|
|
1746
|
+
targetEvalId: newEvalId,
|
|
1747
|
+
distinctTestCount: testCount
|
|
1748
|
+
});
|
|
1749
|
+
const newConfig = structuredClone(sanitizeTracingConfigForPersistence(this.config));
|
|
1750
|
+
newConfig.description = copyDescription;
|
|
1751
|
+
const newPrompts = structuredClone(this.prompts);
|
|
1752
|
+
const newVars = this.vars ? structuredClone(this.vars) : [];
|
|
1753
|
+
const author = getAuthor();
|
|
1754
|
+
const db = await getDb();
|
|
1755
|
+
let copiedCount = 0;
|
|
1756
|
+
await db.transaction(async (tx) => {
|
|
1757
|
+
await tx.insert(evalsTable).values({
|
|
1758
|
+
id: newEvalId,
|
|
1759
|
+
createdAt: Date.now(),
|
|
1760
|
+
author,
|
|
1761
|
+
description: copyDescription,
|
|
1762
|
+
config: sanitizeTracingConfigForPersistence(newConfig),
|
|
1763
|
+
results: {},
|
|
1764
|
+
prompts: newPrompts,
|
|
1765
|
+
vars: newVars,
|
|
1766
|
+
runtimeOptions: sanitizeRuntimeOptions(this.runtimeOptions),
|
|
1767
|
+
isRedteam: newConfig.redteam !== void 0
|
|
1768
|
+
}).run();
|
|
1769
|
+
const promptRels = await tx.select().from(evalsToPromptsTable).where(eq(evalsToPromptsTable.evalId, this.id)).all();
|
|
1770
|
+
if (promptRels.length > 0) await tx.insert(evalsToPromptsTable).values(promptRels.map((rel) => ({
|
|
1771
|
+
evalId: newEvalId,
|
|
1772
|
+
promptId: rel.promptId
|
|
1773
|
+
}))).onConflictDoNothing().run();
|
|
1774
|
+
if (this.config.tags) for (const [tagKey, tagValue] of Object.entries(this.config.tags)) {
|
|
1775
|
+
const tagId = sha256(`${tagKey}:${tagValue}`);
|
|
1776
|
+
await tx.insert(tagsTable).values({
|
|
1777
|
+
id: tagId,
|
|
1778
|
+
name: tagKey,
|
|
1779
|
+
value: tagValue
|
|
1780
|
+
}).onConflictDoNothing().run();
|
|
1781
|
+
await tx.insert(evalsToTagsTable).values({
|
|
1782
|
+
evalId: newEvalId,
|
|
1783
|
+
tagId
|
|
1784
|
+
}).onConflictDoNothing().run();
|
|
1785
|
+
}
|
|
1786
|
+
const datasetRel = await tx.select().from(evalsToDatasetsTable).where(eq(evalsToDatasetsTable.evalId, this.id)).limit(1).all();
|
|
1787
|
+
if (datasetRel.length > 0) await tx.insert(evalsToDatasetsTable).values({
|
|
1788
|
+
evalId: newEvalId,
|
|
1789
|
+
datasetId: datasetRel[0].datasetId
|
|
1790
|
+
}).onConflictDoNothing().run();
|
|
1791
|
+
const BATCH_SIZE = 1e3;
|
|
1792
|
+
let offset = 0;
|
|
1793
|
+
while (true) {
|
|
1794
|
+
const batch = await tx.select().from(evalResultsTable).where(eq(evalResultsTable.evalId, this.id)).orderBy(evalResultsTable.id).limit(BATCH_SIZE).offset(offset).all();
|
|
1795
|
+
if (batch.length === 0) break;
|
|
1796
|
+
const now = Date.now();
|
|
1797
|
+
const copiedResults = batch.map((result) => ({
|
|
1798
|
+
...result,
|
|
1799
|
+
id: crypto.randomUUID(),
|
|
1800
|
+
evalId: newEvalId,
|
|
1801
|
+
createdAt: now,
|
|
1802
|
+
metadata: stripTraceLinkageFromMetadata(result.metadata),
|
|
1803
|
+
updatedAt: now
|
|
1804
|
+
}));
|
|
1805
|
+
await tx.insert(evalResultsTable).values(copiedResults).run();
|
|
1806
|
+
copiedCount += batch.length;
|
|
1807
|
+
offset += BATCH_SIZE;
|
|
1808
|
+
logger.debug("Copied batch of eval results", {
|
|
1809
|
+
sourceEvalId: this.id,
|
|
1810
|
+
targetEvalId: newEvalId,
|
|
1811
|
+
batchSize: batch.length,
|
|
1812
|
+
rowsCopied: copiedCount,
|
|
1813
|
+
distinctTestCount: testCount
|
|
1814
|
+
});
|
|
1815
|
+
}
|
|
1816
|
+
});
|
|
1817
|
+
notifyEvaluationChanged(newEvalId);
|
|
1818
|
+
logger.info("Eval copy completed successfully", {
|
|
1819
|
+
sourceEvalId: this.id,
|
|
1820
|
+
targetEvalId: newEvalId,
|
|
1821
|
+
rowsCopied: copiedCount,
|
|
1822
|
+
distinctTestCount: testCount
|
|
1823
|
+
});
|
|
1824
|
+
return await Eval.findById(newEvalId);
|
|
1825
|
+
}
|
|
1826
|
+
get shared() {
|
|
1827
|
+
return this._shared;
|
|
1828
|
+
}
|
|
1829
|
+
set shared(shared) {
|
|
1830
|
+
this._shared = shared;
|
|
1831
|
+
}
|
|
1832
|
+
};
|
|
1833
|
+
/**
|
|
1834
|
+
* Queries summaries of all evals, optionally for a given dataset.
|
|
1835
|
+
*
|
|
1836
|
+
* @param datasetId - An optional dataset ID to filter by.
|
|
1837
|
+
* @param type - An optional eval type to filter by.
|
|
1838
|
+
* @param includeProviders - An optional flag to include providers in the summary.
|
|
1839
|
+
* @returns A list of eval summaries.
|
|
1840
|
+
*/
|
|
1841
|
+
async function getEvalSummaries(datasetId, type, includeProviders = false) {
|
|
1842
|
+
const db = await getDb();
|
|
1843
|
+
const whereClauses = [];
|
|
1844
|
+
if (datasetId) whereClauses.push(eq(evalsToDatasetsTable.datasetId, datasetId));
|
|
1845
|
+
if (type) {
|
|
1846
|
+
if (type === "redteam") whereClauses.push(eq(evalsTable.isRedteam, true));
|
|
1847
|
+
else whereClauses.push(eq(evalsTable.isRedteam, false));
|
|
1848
|
+
}
|
|
1849
|
+
/**
|
|
1850
|
+
* Deserialize the evals. A few things to note:
|
|
1851
|
+
*
|
|
1852
|
+
* - Test statistics are derived from the prompt metrics as this is the only reliable source of truth
|
|
1853
|
+
* that's written to the evals table.
|
|
1854
|
+
*/
|
|
1855
|
+
return (await db.select({
|
|
1856
|
+
evalId: evalsTable.id,
|
|
1857
|
+
createdAt: evalsTable.createdAt,
|
|
1858
|
+
description: evalsTable.description,
|
|
1859
|
+
datasetId: evalsToDatasetsTable.datasetId,
|
|
1860
|
+
isRedteam: evalsTable.isRedteam,
|
|
1861
|
+
prompts: evalsTable.prompts,
|
|
1862
|
+
config: includeProviders ? evalsTable.config : sql`NULL`
|
|
1863
|
+
}).from(evalsTable).leftJoin(evalsToDatasetsTable, eq(evalsTable.id, evalsToDatasetsTable.evalId)).where(and(...whereClauses)).orderBy(desc(evalsTable.createdAt), desc(evalsTable.id)).all()).map((result) => {
|
|
1864
|
+
const passCount = result.prompts?.reduce((memo, prompt) => {
|
|
1865
|
+
return memo + (prompt.metrics?.testPassCount ?? 0);
|
|
1866
|
+
}, 0) ?? 0;
|
|
1867
|
+
const failCount = result.prompts?.reduce((memo, prompt) => {
|
|
1868
|
+
return memo + (prompt.metrics?.testFailCount ?? 0);
|
|
1869
|
+
}, 0) ?? 0;
|
|
1870
|
+
const testCounts = result.prompts?.map((p) => {
|
|
1871
|
+
return (p.metrics?.testPassCount ?? 0) + (p.metrics?.testFailCount ?? 0) + (p.metrics?.testErrorCount ?? 0);
|
|
1872
|
+
}) ?? [0];
|
|
1873
|
+
const testCount = testCounts.length > 0 ? testCounts[0] : 0;
|
|
1874
|
+
const testRunCount = testCount * (result.prompts?.length ?? 0);
|
|
1875
|
+
const deserializedProviders = [];
|
|
1876
|
+
const providers = result.config?.providers;
|
|
1877
|
+
if (includeProviders) {
|
|
1878
|
+
if (typeof providers === "string") deserializedProviders.push({
|
|
1879
|
+
id: providers,
|
|
1880
|
+
label: null
|
|
1881
|
+
});
|
|
1882
|
+
else if (Array.isArray(providers)) providers.forEach((p) => {
|
|
1883
|
+
if (typeof p === "string") deserializedProviders.push({
|
|
1884
|
+
id: p,
|
|
1885
|
+
label: null
|
|
1886
|
+
});
|
|
1887
|
+
else if (typeof p === "object" && p) {
|
|
1888
|
+
const keys = Object.keys(p);
|
|
1889
|
+
if (keys.length === 1 && !("id" in p)) {
|
|
1890
|
+
const providerId = keys[0];
|
|
1891
|
+
const providerConfig = p[providerId];
|
|
1892
|
+
deserializedProviders.push({
|
|
1893
|
+
id: providerId,
|
|
1894
|
+
label: providerConfig.label ?? null
|
|
1895
|
+
});
|
|
1896
|
+
} else deserializedProviders.push({
|
|
1897
|
+
id: p.id ?? "unknown",
|
|
1898
|
+
label: p.label ?? null
|
|
1899
|
+
});
|
|
1900
|
+
}
|
|
1901
|
+
});
|
|
1902
|
+
}
|
|
1903
|
+
return {
|
|
1904
|
+
evalId: result.evalId,
|
|
1905
|
+
createdAt: result.createdAt,
|
|
1906
|
+
description: result.description,
|
|
1907
|
+
numTests: testCount,
|
|
1908
|
+
datasetId: result.datasetId,
|
|
1909
|
+
isRedteam: Boolean(result.isRedteam),
|
|
1910
|
+
passRate: testRunCount > 0 ? passCount / testRunCount * 100 : 0,
|
|
1911
|
+
label: result.description ? `${result.description} (${result.evalId})` : result.evalId,
|
|
1912
|
+
providers: deserializedProviders,
|
|
1913
|
+
attackSuccessRate: type === "redteam" ? calculateAttackSuccessRate(testRunCount, failCount) : void 0
|
|
1914
|
+
};
|
|
1915
|
+
});
|
|
1916
|
+
}
|
|
1917
|
+
//#endregion
|
|
1918
|
+
export { createEvalId as a, deleteTraceRecordsForEvals as c, combineFilterConditions as i, EvalQueries as n, escapeJsonPathKey as o, buildSafeJsonPath as r, getEvalSummaries as s, Eval as t };
|
|
1919
|
+
|
|
1920
|
+
//# sourceMappingURL=eval-Cer9dPe9.js.map
|