promptfoo 0.72.1 → 0.73.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (470) hide show
  1. package/README.md +5 -5
  2. package/dist/package.json +14 -8
  3. package/dist/src/accounts.d.ts.map +1 -1
  4. package/dist/src/accounts.js +2 -1
  5. package/dist/src/accounts.js.map +1 -1
  6. package/dist/src/assertions/validateAssertions.d.ts +1 -1
  7. package/dist/src/assertions/validateAssertions.d.ts.map +1 -1
  8. package/dist/src/assertions/validateAssertions.js +7 -7
  9. package/dist/src/assertions/validateAssertions.js.map +1 -1
  10. package/dist/src/assertions.d.ts.map +1 -1
  11. package/dist/src/assertions.js +2 -1
  12. package/dist/src/assertions.js.map +1 -1
  13. package/dist/src/cache.js +2 -2
  14. package/dist/src/cache.js.map +1 -1
  15. package/dist/src/commands/eval.d.ts.map +1 -1
  16. package/dist/src/commands/eval.js +10 -0
  17. package/dist/src/commands/eval.js.map +1 -1
  18. package/dist/src/commands/export.d.ts.map +1 -1
  19. package/dist/src/commands/export.js +15 -14
  20. package/dist/src/commands/export.js.map +1 -1
  21. package/dist/src/commands/generate/redteam.d.ts +1 -46
  22. package/dist/src/commands/generate/redteam.d.ts.map +1 -1
  23. package/dist/src/commands/generate/redteam.js +70 -26
  24. package/dist/src/commands/generate/redteam.js.map +1 -1
  25. package/dist/src/commands/import.d.ts.map +1 -1
  26. package/dist/src/commands/import.js +2 -1
  27. package/dist/src/commands/import.js.map +1 -1
  28. package/dist/src/commands/init.d.ts.map +1 -1
  29. package/dist/src/commands/init.js +12 -0
  30. package/dist/src/commands/init.js.map +1 -1
  31. package/dist/src/commands/redteam.d.ts.map +1 -1
  32. package/dist/src/commands/redteam.js +72 -18
  33. package/dist/src/commands/redteam.js.map +1 -1
  34. package/dist/src/commands/view.d.ts.map +1 -1
  35. package/dist/src/commands/view.js +2 -1
  36. package/dist/src/commands/view.js.map +1 -1
  37. package/dist/src/config.d.ts.map +1 -1
  38. package/dist/src/config.js +2 -20
  39. package/dist/src/config.js.map +1 -1
  40. package/dist/src/configTypes.d.ts +7 -0
  41. package/dist/src/configTypes.d.ts.map +1 -0
  42. package/dist/src/configTypes.js +3 -0
  43. package/dist/src/configTypes.js.map +1 -0
  44. package/dist/src/database/index.d.ts +4 -0
  45. package/dist/src/database/index.d.ts.map +1 -0
  46. package/dist/src/database/index.js +50 -0
  47. package/dist/src/database/index.js.map +1 -0
  48. package/dist/src/{database.d.ts → database/operations.d.ts} +173 -115
  49. package/dist/src/{database.d.ts.map → database/operations.d.ts.map} +1 -1
  50. package/dist/src/{database.js → database/operations.js} +1 -25
  51. package/dist/src/database/operations.js.map +1 -0
  52. package/dist/src/evaluator.js +2 -2
  53. package/dist/src/evaluator.js.map +1 -1
  54. package/dist/src/globalConfig.d.ts +1 -7
  55. package/dist/src/globalConfig.d.ts.map +1 -1
  56. package/dist/src/globalConfig.js +3 -3
  57. package/dist/src/globalConfig.js.map +1 -1
  58. package/dist/src/matchers.d.ts.map +1 -1
  59. package/dist/src/matchers.js +6 -2
  60. package/dist/src/matchers.js.map +1 -1
  61. package/dist/src/prompts/grading.js +2 -2
  62. package/dist/src/prompts/processors/python.js +4 -4
  63. package/dist/src/prompts/processors/python.js.map +1 -1
  64. package/dist/src/providers/anthropic.d.ts +1 -1
  65. package/dist/src/providers/anthropic.d.ts.map +1 -1
  66. package/dist/src/providers/bam.d.ts +1 -1
  67. package/dist/src/providers/bam.d.ts.map +1 -1
  68. package/dist/src/providers/bedrock.d.ts +1 -1
  69. package/dist/src/providers/bedrock.d.ts.map +1 -1
  70. package/dist/src/providers/cohere.d.ts.map +1 -1
  71. package/dist/src/providers/cohere.js +4 -1
  72. package/dist/src/providers/cohere.js.map +1 -1
  73. package/dist/src/providers/http.d.ts +1 -1
  74. package/dist/src/providers/http.d.ts.map +1 -1
  75. package/dist/src/providers/http.js +3 -3
  76. package/dist/src/providers/http.js.map +1 -1
  77. package/dist/src/providers/llama.d.ts +1 -1
  78. package/dist/src/providers/llama.d.ts.map +1 -1
  79. package/dist/src/providers/localai.d.ts +1 -1
  80. package/dist/src/providers/localai.d.ts.map +1 -1
  81. package/dist/src/providers/ollama.d.ts +1 -1
  82. package/dist/src/providers/ollama.d.ts.map +1 -1
  83. package/dist/src/providers/openai.d.ts +1 -1
  84. package/dist/src/providers/openai.d.ts.map +1 -1
  85. package/dist/src/providers/openai.js +48 -50
  86. package/dist/src/providers/openai.js.map +1 -1
  87. package/dist/src/providers/palm.d.ts +1 -1
  88. package/dist/src/providers/palm.d.ts.map +1 -1
  89. package/dist/src/providers/pythonCompletion.d.ts.map +1 -1
  90. package/dist/src/providers/pythonCompletion.js +6 -5
  91. package/dist/src/providers/pythonCompletion.js.map +1 -1
  92. package/dist/src/providers/replicate.js +2 -2
  93. package/dist/src/providers/replicate.js.map +1 -1
  94. package/dist/src/providers/scriptCompletion.js +3 -3
  95. package/dist/src/providers/scriptCompletion.js.map +1 -1
  96. package/dist/src/providers/vertex.d.ts +1 -1
  97. package/dist/src/providers/vertex.d.ts.map +1 -1
  98. package/dist/src/providers/vertex.js +23 -10
  99. package/dist/src/providers/vertex.js.map +1 -1
  100. package/dist/src/providers/vertexUtil.d.ts +2 -1
  101. package/dist/src/providers/vertexUtil.d.ts.map +1 -1
  102. package/dist/src/providers/vertexUtil.js.map +1 -1
  103. package/dist/src/providers/webhook.d.ts +1 -1
  104. package/dist/src/providers/webhook.d.ts.map +1 -1
  105. package/dist/src/providers.d.ts.map +1 -1
  106. package/dist/src/providers.js +5 -2
  107. package/dist/src/providers.js.map +1 -1
  108. package/dist/src/python/pythonUtils.d.ts +4 -0
  109. package/dist/src/python/pythonUtils.d.ts.map +1 -0
  110. package/dist/src/python/pythonUtils.js +51 -0
  111. package/dist/src/python/pythonUtils.js.map +1 -0
  112. package/dist/src/python/wrapper.d.ts +0 -10
  113. package/dist/src/python/wrapper.d.ts.map +1 -1
  114. package/dist/src/python/wrapper.js +2 -49
  115. package/dist/src/python/wrapper.js.map +1 -1
  116. package/dist/src/redteam/constants.d.ts +60 -3
  117. package/dist/src/redteam/constants.d.ts.map +1 -1
  118. package/dist/src/redteam/constants.js +71 -10
  119. package/dist/src/redteam/constants.js.map +1 -1
  120. package/dist/src/redteam/index.d.ts +15 -4
  121. package/dist/src/redteam/index.d.ts.map +1 -1
  122. package/dist/src/redteam/index.js +110 -33
  123. package/dist/src/redteam/index.js.map +1 -1
  124. package/dist/src/redteam/plugins/base.d.ts +10 -13
  125. package/dist/src/redteam/plugins/base.d.ts.map +1 -1
  126. package/dist/src/redteam/plugins/base.js +36 -20
  127. package/dist/src/redteam/plugins/base.js.map +1 -1
  128. package/dist/src/redteam/plugins/debugInterface.d.ts +7 -0
  129. package/dist/src/redteam/plugins/debugInterface.d.ts.map +1 -0
  130. package/dist/src/redteam/plugins/debugInterface.js +49 -0
  131. package/dist/src/redteam/plugins/debugInterface.js.map +1 -0
  132. package/dist/src/redteam/plugins/harmful.d.ts +1 -54
  133. package/dist/src/redteam/plugins/harmful.d.ts.map +1 -1
  134. package/dist/src/redteam/plugins/harmful.js +8 -51
  135. package/dist/src/redteam/plugins/harmful.js.map +1 -1
  136. package/dist/src/redteam/plugins/pii.d.ts +9 -10
  137. package/dist/src/redteam/plugins/pii.d.ts.map +1 -1
  138. package/dist/src/redteam/plugins/pii.js +33 -53
  139. package/dist/src/redteam/plugins/pii.js.map +1 -1
  140. package/dist/src/redteam/plugins/rbac.d.ts +7 -0
  141. package/dist/src/redteam/plugins/rbac.d.ts.map +1 -0
  142. package/dist/src/redteam/plugins/rbac.js +49 -0
  143. package/dist/src/redteam/plugins/rbac.js.map +1 -0
  144. package/dist/src/redteam/plugins/shellInjection.d.ts +7 -0
  145. package/dist/src/redteam/plugins/shellInjection.d.ts.map +1 -0
  146. package/dist/src/redteam/plugins/shellInjection.js +54 -0
  147. package/dist/src/redteam/plugins/shellInjection.js.map +1 -0
  148. package/dist/src/redteam/plugins/sqlInjection.d.ts +7 -0
  149. package/dist/src/redteam/plugins/sqlInjection.d.ts.map +1 -0
  150. package/dist/src/redteam/plugins/sqlInjection.js +44 -0
  151. package/dist/src/redteam/plugins/sqlInjection.js.map +1 -0
  152. package/dist/src/redteam/providers/iterative.d.ts.map +1 -1
  153. package/dist/src/redteam/providers/iterative.js +2 -1
  154. package/dist/src/redteam/providers/iterative.js.map +1 -1
  155. package/dist/src/redteam/strategies/injections.d.ts.map +1 -0
  156. package/dist/src/redteam/{methods → strategies}/injections.js +0 -12
  157. package/dist/src/redteam/strategies/injections.js.map +1 -0
  158. package/dist/src/redteam/strategies/iterative.d.ts.map +1 -0
  159. package/dist/src/redteam/strategies/iterative.js.map +1 -0
  160. package/dist/src/redteam/types.d.ts +196 -0
  161. package/dist/src/redteam/types.d.ts.map +1 -0
  162. package/dist/src/redteam/types.js +124 -0
  163. package/dist/src/redteam/types.js.map +1 -0
  164. package/dist/src/redteam/util.d.ts +22 -0
  165. package/dist/src/redteam/util.d.ts.map +1 -0
  166. package/dist/src/redteam/util.js +56 -0
  167. package/dist/src/redteam/util.js.map +1 -0
  168. package/dist/src/testCases.d.ts +1 -2
  169. package/dist/src/testCases.d.ts.map +1 -1
  170. package/dist/src/testCases.js.map +1 -1
  171. package/dist/src/types/databaseTypes.d.ts +17 -0
  172. package/dist/src/types/databaseTypes.d.ts.map +1 -0
  173. package/dist/src/types/databaseTypes.js +3 -0
  174. package/dist/src/types/databaseTypes.js.map +1 -0
  175. package/dist/src/{types.d.ts → types/index.d.ts} +4296 -1425
  176. package/dist/src/{types.d.ts.map → types/index.d.ts.map} +1 -1
  177. package/dist/src/{types.js → types/index.js} +38 -9
  178. package/dist/src/types/index.js.map +1 -0
  179. package/dist/src/util/config.d.ts +3 -0
  180. package/dist/src/util/config.d.ts.map +1 -0
  181. package/dist/src/util/config.js +42 -0
  182. package/dist/src/util/config.js.map +1 -0
  183. package/dist/src/util/index.d.ts +41 -25
  184. package/dist/src/util/index.d.ts.map +1 -1
  185. package/dist/src/util/index.js +81 -119
  186. package/dist/src/util/index.js.map +1 -1
  187. package/dist/src/util/json.d.ts +3 -0
  188. package/dist/src/util/json.d.ts.map +1 -0
  189. package/dist/src/util/json.js +27 -0
  190. package/dist/src/util/json.js.map +1 -0
  191. package/dist/src/web/nextui/404/index.html +1 -1
  192. package/dist/src/web/nextui/404.html +1 -1
  193. package/dist/src/web/nextui/_next/static/chunks/155-4e319e68476266ee.js +1 -0
  194. package/dist/src/web/nextui/_next/static/chunks/163-93bab94bc04ae71b.js +6 -0
  195. package/dist/src/web/nextui/_next/static/chunks/{258-4acb452fe85cff6f.js → 258-b6257e5de9d0e2c7.js} +1 -1
  196. package/dist/src/web/nextui/_next/static/chunks/281-64d9f1415a301ee5.js +1 -0
  197. package/dist/src/web/nextui/_next/static/chunks/304-cf667fe8f06238b4.js +1 -0
  198. package/dist/src/web/nextui/_next/static/chunks/322-b47b6cc3f5b5fdb8.js +1 -0
  199. package/dist/src/web/nextui/_next/static/chunks/325-0d36870ade5e5263.js +1 -0
  200. package/dist/src/web/nextui/_next/static/chunks/339-79124d204fa988a3.js +1 -0
  201. package/dist/src/web/nextui/_next/static/chunks/378-c135e497df1864cb.js +1 -0
  202. package/dist/src/web/nextui/_next/static/chunks/476-0afb5eb266c57b7f.js +17 -0
  203. package/dist/src/web/nextui/_next/static/chunks/493-ebd12f00541c4969.js +2 -0
  204. package/dist/src/web/nextui/_next/static/chunks/497-e280a5610a3d7d42.js +32 -0
  205. package/dist/src/web/nextui/_next/static/chunks/515-e06d044f12d8a1bd.js +1 -0
  206. package/dist/src/web/nextui/_next/static/chunks/69-5e4d5e60859a86d2.js +1 -0
  207. package/dist/src/web/nextui/_next/static/chunks/737-32d5472455807d7a.js +1 -0
  208. package/dist/src/web/nextui/_next/static/chunks/903-7cc440d9f9e9f95d.js +97 -0
  209. package/dist/src/web/nextui/_next/static/chunks/905-78cd666f27891ee6.js +28 -0
  210. package/dist/src/web/nextui/_next/static/chunks/916-b92fea2ab6136411.js +1 -0
  211. package/dist/src/web/nextui/_next/static/chunks/969-6ab6c8f4158da970.js +1 -0
  212. package/dist/src/web/nextui/_next/static/chunks/app/auth/login/page-7247b17e8f179a46.js +1 -0
  213. package/dist/src/web/nextui/_next/static/chunks/app/auth/signup/page-8560afaf494f9882.js +1 -0
  214. package/dist/src/web/nextui/_next/static/chunks/app/datasets/page-6e6ec3c778ccd110.js +1 -0
  215. package/dist/src/web/nextui/_next/static/chunks/app/eval/[id]/not-found-fe10d5df88bc44ef.js +1 -0
  216. package/dist/src/web/nextui/_next/static/chunks/app/eval/[id]/{page-0a39d3450aa09dda.js → page-057e5eb83e0f614b.js} +1 -1
  217. package/dist/src/web/nextui/_next/static/chunks/app/eval/page-88fa70fc5bf755bc.js +1 -0
  218. package/dist/src/web/nextui/_next/static/chunks/app/layout-15abf0d1049cb47c.js +1 -0
  219. package/dist/src/web/nextui/_next/static/chunks/app/{page-5650318e57510b6c.js → page-122e9cfa52eb218a.js} +1 -1
  220. package/dist/src/web/nextui/_next/static/chunks/app/progress/page-a62ca531a4bb4149.js +1 -0
  221. package/dist/src/web/nextui/_next/static/chunks/app/prompts/page-10bb2e571670139c.js +1 -0
  222. package/dist/src/web/nextui/_next/static/chunks/app/report/page-a8b83960f08e2bb2.js +1 -0
  223. package/dist/src/web/nextui/_next/static/chunks/app/setup/page-6ea3e180c3116fb2.js +1 -0
  224. package/dist/src/web/nextui/_next/static/chunks/{main-app-929a26b3c8cd3f7a.js → main-app-7a1376166cb8b72e.js} +1 -1
  225. package/dist/src/web/nextui/_next/static/chunks/{webpack-c9f728822666f852.js → webpack-ee33d95b3e219985.js} +1 -1
  226. package/dist/src/web/nextui/_next/static/css/13f881e4290b6d59.css +1 -0
  227. package/dist/src/web/nextui/_next/static/css/87b5e6e04efd27e5.css +1 -0
  228. package/dist/src/web/nextui/_next/static/css/e17fdafd8599f69b.css +1 -0
  229. package/dist/src/web/nextui/_next/static/css/eb523daddb89dfc1.css +1 -0
  230. package/dist/src/web/nextui/auth/login/index.html +1 -1
  231. package/dist/src/web/nextui/auth/login/index.txt +6 -6
  232. package/dist/src/web/nextui/auth/signup/index.html +1 -1
  233. package/dist/src/web/nextui/auth/signup/index.txt +6 -6
  234. package/dist/src/web/nextui/datasets/index.html +1 -1
  235. package/dist/src/web/nextui/datasets/index.txt +6 -6
  236. package/dist/src/web/nextui/eval/index.html +1 -1
  237. package/dist/src/web/nextui/eval/index.txt +8 -8
  238. package/dist/src/web/nextui/index.html +1 -1
  239. package/dist/src/web/nextui/index.txt +5 -5
  240. package/dist/src/web/nextui/logo-panda.svg +91 -0
  241. package/dist/src/web/nextui/progress/index.html +1 -1
  242. package/dist/src/web/nextui/progress/index.txt +6 -6
  243. package/dist/src/web/nextui/prompts/index.html +1 -1
  244. package/dist/src/web/nextui/prompts/index.txt +6 -6
  245. package/dist/src/web/nextui/report/index.html +1 -1
  246. package/dist/src/web/nextui/report/index.txt +8 -8
  247. package/dist/src/web/nextui/setup/index.html +1 -1
  248. package/dist/src/web/nextui/setup/index.txt +7 -7
  249. package/dist/test/__mocks__/tempCustomModule.d.ts +13 -0
  250. package/dist/test/__mocks__/tempCustomModule.d.ts.map +1 -0
  251. package/dist/test/__mocks__/tempCustomModule.js +15 -0
  252. package/dist/test/__mocks__/tempCustomModule.js.map +1 -0
  253. package/dist/test/account.test.d.ts +2 -0
  254. package/dist/test/account.test.d.ts.map +1 -0
  255. package/dist/test/account.test.js +46 -0
  256. package/dist/test/account.test.js.map +1 -0
  257. package/dist/test/assertions/AssertionResult.test.d.ts +2 -0
  258. package/dist/test/assertions/AssertionResult.test.d.ts.map +1 -0
  259. package/dist/test/assertions/AssertionResult.test.js +184 -0
  260. package/dist/test/assertions/AssertionResult.test.js.map +1 -0
  261. package/dist/test/assertions/validateAssertions.test.d.ts +2 -0
  262. package/dist/test/assertions/validateAssertions.test.d.ts.map +1 -0
  263. package/dist/test/assertions/validateAssertions.test.js +40 -0
  264. package/dist/test/assertions/validateAssertions.test.js.map +1 -0
  265. package/dist/test/assertions.test.d.ts +2 -0
  266. package/dist/test/assertions.test.d.ts.map +1 -0
  267. package/dist/test/assertions.test.js +3162 -0
  268. package/dist/test/assertions.test.js.map +1 -0
  269. package/dist/test/cache.test.d.ts +2 -0
  270. package/dist/test/cache.test.d.ts.map +1 -0
  271. package/dist/test/cache.test.js +90 -0
  272. package/dist/test/cache.test.js.map +1 -0
  273. package/dist/test/checkNodeVersion.test.d.ts +2 -0
  274. package/dist/test/checkNodeVersion.test.d.ts.map +1 -0
  275. package/dist/test/checkNodeVersion.test.js +85 -0
  276. package/dist/test/checkNodeVersion.test.js.map +1 -0
  277. package/dist/test/commands/eval/filterFailingTests.test.d.ts +2 -0
  278. package/dist/test/commands/eval/filterFailingTests.test.d.ts.map +1 -0
  279. package/dist/test/commands/eval/filterFailingTests.test.js +84 -0
  280. package/dist/test/commands/eval/filterFailingTests.test.js.map +1 -0
  281. package/dist/test/commands/eval/filterProviders.test.d.ts +2 -0
  282. package/dist/test/commands/eval/filterProviders.test.d.ts.map +1 -0
  283. package/dist/test/commands/eval/filterProviders.test.js +50 -0
  284. package/dist/test/commands/eval/filterProviders.test.js.map +1 -0
  285. package/dist/test/commands/eval/filterTests.test.d.ts +2 -0
  286. package/dist/test/commands/eval/filterTests.test.d.ts.map +1 -0
  287. package/dist/test/commands/eval/filterTests.test.js +51 -0
  288. package/dist/test/commands/eval/filterTests.test.js.map +1 -0
  289. package/dist/test/config.test.d.ts +2 -0
  290. package/dist/test/config.test.d.ts.map +1 -0
  291. package/dist/test/config.test.js +404 -0
  292. package/dist/test/config.test.js.map +1 -0
  293. package/dist/test/csv.test.d.ts +2 -0
  294. package/dist/test/csv.test.d.ts.map +1 -0
  295. package/dist/test/csv.test.js +239 -0
  296. package/dist/test/csv.test.js.map +1 -0
  297. package/dist/test/evaluator.test.d.ts +2 -0
  298. package/dist/test/evaluator.test.d.ts.map +1 -0
  299. package/dist/test/evaluator.test.js +922 -0
  300. package/dist/test/evaluator.test.js.map +1 -0
  301. package/dist/test/globalConfig.test.d.ts +2 -0
  302. package/dist/test/globalConfig.test.d.ts.map +1 -0
  303. package/dist/test/globalConfig.test.js +91 -0
  304. package/dist/test/globalConfig.test.js.map +1 -0
  305. package/dist/test/is-sql-tests/node-sql-parser.test.d.ts +2 -0
  306. package/dist/test/is-sql-tests/node-sql-parser.test.d.ts.map +1 -0
  307. package/dist/test/is-sql-tests/node-sql-parser.test.js +179 -0
  308. package/dist/test/is-sql-tests/node-sql-parser.test.js.map +1 -0
  309. package/dist/test/matchers.test.d.ts +2 -0
  310. package/dist/test/matchers.test.d.ts.map +1 -0
  311. package/dist/test/matchers.test.js +807 -0
  312. package/dist/test/matchers.test.js.map +1 -0
  313. package/dist/test/prompts.processors.javascript.test.d.ts +2 -0
  314. package/dist/test/prompts.processors.javascript.test.d.ts.map +1 -0
  315. package/dist/test/prompts.processors.javascript.test.js +93 -0
  316. package/dist/test/prompts.processors.javascript.test.js.map +1 -0
  317. package/dist/test/prompts.processors.json.test.d.ts +2 -0
  318. package/dist/test/prompts.processors.json.test.d.ts.map +1 -0
  319. package/dist/test/prompts.processors.json.test.js +67 -0
  320. package/dist/test/prompts.processors.json.test.js.map +1 -0
  321. package/dist/test/prompts.processors.jsonl.test.d.ts +2 -0
  322. package/dist/test/prompts.processors.jsonl.test.d.ts.map +1 -0
  323. package/dist/test/prompts.processors.jsonl.test.js +99 -0
  324. package/dist/test/prompts.processors.jsonl.test.js.map +1 -0
  325. package/dist/test/prompts.processors.python.test.d.ts +2 -0
  326. package/dist/test/prompts.processors.python.test.d.ts.map +1 -0
  327. package/dist/test/prompts.processors.python.test.js +100 -0
  328. package/dist/test/prompts.processors.python.test.js.map +1 -0
  329. package/dist/test/prompts.processors.python.utils.test.d.ts +2 -0
  330. package/dist/test/prompts.processors.python.utils.test.d.ts.map +1 -0
  331. package/dist/test/prompts.processors.python.utils.test.js +68 -0
  332. package/dist/test/prompts.processors.python.utils.test.js.map +1 -0
  333. package/dist/test/prompts.processors.string.test.d.ts +2 -0
  334. package/dist/test/prompts.processors.string.test.d.ts.map +1 -0
  335. package/dist/test/prompts.processors.string.test.js +24 -0
  336. package/dist/test/prompts.processors.string.test.js.map +1 -0
  337. package/dist/test/prompts.processors.text.test.d.ts +2 -0
  338. package/dist/test/prompts.processors.text.test.d.ts.map +1 -0
  339. package/dist/test/prompts.processors.text.test.js +109 -0
  340. package/dist/test/prompts.processors.text.test.js.map +1 -0
  341. package/dist/test/prompts.processors.yaml.test.d.ts +2 -0
  342. package/dist/test/prompts.processors.yaml.test.d.ts.map +1 -0
  343. package/dist/test/prompts.processors.yaml.test.js +76 -0
  344. package/dist/test/prompts.processors.yaml.test.js.map +1 -0
  345. package/dist/test/prompts.test.d.ts +2 -0
  346. package/dist/test/prompts.test.d.ts.map +1 -0
  347. package/dist/test/prompts.test.js +562 -0
  348. package/dist/test/prompts.test.js.map +1 -0
  349. package/dist/test/prompts.utils.test.d.ts +2 -0
  350. package/dist/test/prompts.utils.test.d.ts.map +1 -0
  351. package/dist/test/prompts.utils.test.js +123 -0
  352. package/dist/test/prompts.utils.test.js.map +1 -0
  353. package/dist/test/providers.anthropic.test.d.ts +2 -0
  354. package/dist/test/providers.anthropic.test.d.ts.map +1 -0
  355. package/dist/test/providers.anthropic.test.js +520 -0
  356. package/dist/test/providers.anthropic.test.js.map +1 -0
  357. package/dist/test/providers.azure.test.d.ts +2 -0
  358. package/dist/test/providers.azure.test.d.ts.map +1 -0
  359. package/dist/test/providers.azure.test.js +96 -0
  360. package/dist/test/providers.azure.test.js.map +1 -0
  361. package/dist/test/providers.bedrock.test.d.ts +2 -0
  362. package/dist/test/providers.bedrock.test.d.ts.map +1 -0
  363. package/dist/test/providers.bedrock.test.js +349 -0
  364. package/dist/test/providers.bedrock.test.js.map +1 -0
  365. package/dist/test/providers.http.test.d.ts +2 -0
  366. package/dist/test/providers.http.test.d.ts.map +1 -0
  367. package/dist/test/providers.http.test.js +130 -0
  368. package/dist/test/providers.http.test.js.map +1 -0
  369. package/dist/test/providers.llama.test.d.ts +2 -0
  370. package/dist/test/providers.llama.test.d.ts.map +1 -0
  371. package/dist/test/providers.llama.test.js +101 -0
  372. package/dist/test/providers.llama.test.js.map +1 -0
  373. package/dist/test/providers.pythonCompletion.test.d.ts +2 -0
  374. package/dist/test/providers.pythonCompletion.test.d.ts.map +1 -0
  375. package/dist/test/providers.pythonCompletion.test.js +149 -0
  376. package/dist/test/providers.pythonCompletion.test.js.map +1 -0
  377. package/dist/test/providers.test.d.ts +2 -0
  378. package/dist/test/providers.test.d.ts.map +1 -0
  379. package/dist/test/providers.test.js +883 -0
  380. package/dist/test/providers.test.js.map +1 -0
  381. package/dist/test/providers.vertex.test.d.ts +2 -0
  382. package/dist/test/providers.vertex.test.d.ts.map +1 -0
  383. package/dist/test/providers.vertex.test.js +153 -0
  384. package/dist/test/providers.vertex.test.js.map +1 -0
  385. package/dist/test/pythonWrapper.test.d.ts +2 -0
  386. package/dist/test/pythonWrapper.test.d.ts.map +1 -0
  387. package/dist/test/pythonWrapper.test.js +65 -0
  388. package/dist/test/pythonWrapper.test.js.map +1 -0
  389. package/dist/test/redteam/plugins/base.test.d.ts +2 -0
  390. package/dist/test/redteam/plugins/base.test.d.ts.map +1 -0
  391. package/dist/test/redteam/plugins/base.test.js +149 -0
  392. package/dist/test/redteam/plugins/base.test.js.map +1 -0
  393. package/dist/test/redteam/purpose.test.d.ts +2 -0
  394. package/dist/test/redteam/purpose.test.d.ts.map +1 -0
  395. package/dist/test/redteam/purpose.test.js +37 -0
  396. package/dist/test/redteam/purpose.test.js.map +1 -0
  397. package/dist/test/redteam/types.test.d.ts +2 -0
  398. package/dist/test/redteam/types.test.d.ts.map +1 -0
  399. package/dist/test/redteam/types.test.js +325 -0
  400. package/dist/test/redteam/types.test.js.map +1 -0
  401. package/dist/test/redteam/util.test.d.ts +2 -0
  402. package/dist/test/redteam/util.test.d.ts.map +1 -0
  403. package/dist/test/redteam/util.test.js +99 -0
  404. package/dist/test/redteam/util.test.js.map +1 -0
  405. package/dist/test/telemetry.test.d.ts +2 -0
  406. package/dist/test/telemetry.test.d.ts.map +1 -0
  407. package/dist/test/telemetry.test.js +68 -0
  408. package/dist/test/telemetry.test.js.map +1 -0
  409. package/dist/test/testCases.test.d.ts +2 -0
  410. package/dist/test/testCases.test.d.ts.map +1 -0
  411. package/dist/test/testCases.test.js +362 -0
  412. package/dist/test/testCases.test.js.map +1 -0
  413. package/dist/test/updates.test.d.ts +2 -0
  414. package/dist/test/updates.test.d.ts.map +1 -0
  415. package/dist/test/updates.test.js +63 -0
  416. package/dist/test/updates.test.js.map +1 -0
  417. package/dist/test/util.templates.test.d.ts +2 -0
  418. package/dist/test/util.templates.test.d.ts.map +1 -0
  419. package/dist/test/util.templates.test.js +75 -0
  420. package/dist/test/util.templates.test.js.map +1 -0
  421. package/dist/test/util.test.d.ts +2 -0
  422. package/dist/test/util.test.d.ts.map +1 -0
  423. package/dist/test/util.test.js +661 -0
  424. package/dist/test/util.test.js.map +1 -0
  425. package/dist/test/utils.d.ts +6 -0
  426. package/dist/test/utils.d.ts.map +1 -0
  427. package/dist/test/utils.js +16 -0
  428. package/dist/test/utils.js.map +1 -0
  429. package/package.json +14 -8
  430. package/dist/src/database.js.map +0 -1
  431. package/dist/src/redteam/methods/injections.d.ts.map +0 -1
  432. package/dist/src/redteam/methods/injections.js.map +0 -1
  433. package/dist/src/redteam/methods/iterative.d.ts.map +0 -1
  434. package/dist/src/redteam/methods/iterative.js.map +0 -1
  435. package/dist/src/types.js.map +0 -1
  436. package/dist/src/web/nextui/_next/static/chunks/163-e65e0f7f442a0c72.js +0 -6
  437. package/dist/src/web/nextui/_next/static/chunks/180-46db19289d856800.js +0 -1
  438. package/dist/src/web/nextui/_next/static/chunks/304-9d57a2251034b801.js +0 -1
  439. package/dist/src/web/nextui/_next/static/chunks/322-4a0fc9b0508f47e8.js +0 -1
  440. package/dist/src/web/nextui/_next/static/chunks/339-db5bd05e24dde905.js +0 -1
  441. package/dist/src/web/nextui/_next/static/chunks/374-d40afe599198abd3.js +0 -1
  442. package/dist/src/web/nextui/_next/static/chunks/378-e22c8aeb8e031fad.js +0 -1
  443. package/dist/src/web/nextui/_next/static/chunks/448-4da3bf74eae4996a.js +0 -97
  444. package/dist/src/web/nextui/_next/static/chunks/53-fae6e50ace6c83a1.js +0 -1
  445. package/dist/src/web/nextui/_next/static/chunks/578-8efe57f906f7573c.js +0 -44
  446. package/dist/src/web/nextui/_next/static/chunks/620-7a5a7bf6e1fe49e5.js +0 -1
  447. package/dist/src/web/nextui/_next/static/chunks/737-538f50dc31cc8c49.js +0 -1
  448. package/dist/src/web/nextui/_next/static/chunks/905-0da344cee75690e7.js +0 -32
  449. package/dist/src/web/nextui/_next/static/chunks/932-75585b3be8ce494d.js +0 -1
  450. package/dist/src/web/nextui/_next/static/chunks/973-ffe3726c956d08ef.js +0 -2
  451. package/dist/src/web/nextui/_next/static/chunks/995-803c74b81e7bf6cd.js +0 -1
  452. package/dist/src/web/nextui/_next/static/chunks/app/auth/login/page-2e2c0c725127ea2d.js +0 -1
  453. package/dist/src/web/nextui/_next/static/chunks/app/auth/signup/page-ccdb1f6890601666.js +0 -1
  454. package/dist/src/web/nextui/_next/static/chunks/app/datasets/page-642db4f4a8e8ba40.js +0 -1
  455. package/dist/src/web/nextui/_next/static/chunks/app/eval/[id]/not-found-ce320e6d1e6d1d23.js +0 -1
  456. package/dist/src/web/nextui/_next/static/chunks/app/eval/page-32eaa14d2384c5b0.js +0 -1
  457. package/dist/src/web/nextui/_next/static/chunks/app/layout-4282b1d33566e258.js +0 -1
  458. package/dist/src/web/nextui/_next/static/chunks/app/progress/page-462526776efd6fd6.js +0 -1
  459. package/dist/src/web/nextui/_next/static/chunks/app/prompts/page-0ae78bc0bf7c56bc.js +0 -1
  460. package/dist/src/web/nextui/_next/static/chunks/app/report/page-e4f7851d41eb0f92.js +0 -1
  461. package/dist/src/web/nextui/_next/static/chunks/app/setup/page-6cde750ec428cd75.js +0 -1
  462. package/dist/src/web/nextui/_next/static/css/35ab7ce8025438b0.css +0 -1
  463. package/dist/src/web/nextui/_next/static/css/5bd2f45de1f3ba83.css +0 -1
  464. package/dist/src/web/nextui/_next/static/css/94b771e23fc5d5f5.css +0 -1
  465. package/dist/src/web/nextui/_next/static/css/dab5d695b3657d59.css +0 -1
  466. /package/dist/src/redteam/{methods → strategies}/injections.d.ts +0 -0
  467. /package/dist/src/redteam/{methods → strategies}/iterative.d.ts +0 -0
  468. /package/dist/src/redteam/{methods → strategies}/iterative.js +0 -0
  469. /package/dist/src/web/nextui/_next/static/{8E4q0Tmu22G1wENZyXEq0 → L-tpppAe26U-euPv62afH}/_buildManifest.js +0 -0
  470. /package/dist/src/web/nextui/_next/static/{8E4q0Tmu22G1wENZyXEq0 → L-tpppAe26U-euPv62afH}/_ssgManifest.js +0 -0
@@ -0,0 +1,922 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const fs = __importStar(require("fs"));
30
+ const glob_1 = __importDefault(require("glob"));
31
+ const path = __importStar(require("path"));
32
+ const evaluator_1 = require("../src/evaluator");
33
+ jest.mock('node-fetch', () => jest.fn());
34
+ jest.mock('proxy-agent', () => ({
35
+ ProxyAgent: jest.fn().mockImplementation(() => ({})),
36
+ }));
37
+ jest.mock('glob', () => ({
38
+ globSync: jest.fn(),
39
+ }));
40
+ jest.mock('fs', () => ({
41
+ readFileSync: jest.fn(),
42
+ writeFileSync: jest.fn(),
43
+ statSync: jest.fn(),
44
+ readdirSync: jest.fn(),
45
+ existsSync: jest.fn(),
46
+ mkdirSync: jest.fn(),
47
+ promises: {
48
+ readFile: jest.fn(),
49
+ },
50
+ }));
51
+ jest.mock('../src/esm');
52
+ jest.mock('../src/database', () => ({
53
+ getDb: jest.fn(),
54
+ }));
55
+ const mockApiProvider = {
56
+ id: jest.fn().mockReturnValue('test-provider'),
57
+ callApi: jest.fn().mockResolvedValue({
58
+ output: 'Test output',
59
+ tokenUsage: { total: 10, prompt: 5, completion: 5, cached: 0 },
60
+ }),
61
+ };
62
+ const mockGradingApiProviderPasses = {
63
+ id: jest.fn().mockReturnValue('test-grading-provider'),
64
+ callApi: jest.fn().mockResolvedValue({
65
+ output: JSON.stringify({ pass: true, reason: 'Test grading output' }),
66
+ tokenUsage: { total: 10, prompt: 5, completion: 5, cached: 0 },
67
+ }),
68
+ };
69
+ const mockGradingApiProviderFails = {
70
+ id: jest.fn().mockReturnValue('test-grading-provider'),
71
+ callApi: jest.fn().mockResolvedValue({
72
+ output: JSON.stringify({ pass: false, reason: 'Grading failed reason' }),
73
+ tokenUsage: { total: 10, prompt: 5, completion: 5, cached: 0 },
74
+ }),
75
+ };
76
+ function toPrompt(text) {
77
+ return { raw: text, label: text };
78
+ }
79
+ describe('evaluator', () => {
80
+ beforeEach(() => {
81
+ jest.clearAllMocks();
82
+ });
83
+ afterEach(() => {
84
+ jest.clearAllMocks();
85
+ });
86
+ it('evaluate with vars', async () => {
87
+ const testSuite = {
88
+ providers: [mockApiProvider],
89
+ prompts: [toPrompt('Test prompt {{ var1 }} {{ var2 }}')],
90
+ tests: [
91
+ {
92
+ vars: { var1: 'value1', var2: 'value2' },
93
+ },
94
+ ],
95
+ };
96
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
97
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(1);
98
+ expect(summary.stats.successes).toBe(1);
99
+ expect(summary.stats.failures).toBe(0);
100
+ expect(summary.stats.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5, cached: 0 });
101
+ expect(summary.results[0].prompt.raw).toBe('Test prompt value1 value2');
102
+ expect(summary.results[0].prompt.label).toBe('Test prompt {{ var1 }} {{ var2 }}');
103
+ expect(summary.results[0].response?.output).toBe('Test output');
104
+ });
105
+ it('evaluate with vars - no escaping', async () => {
106
+ const testSuite = {
107
+ providers: [mockApiProvider],
108
+ prompts: [toPrompt('Test prompt {{ var1 }} {{ var2 }}')],
109
+ tests: [
110
+ {
111
+ vars: { var1: '1 < 2', var2: 'he said "hello world"...' },
112
+ },
113
+ ],
114
+ };
115
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
116
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(1);
117
+ expect(summary.stats.successes).toBe(1);
118
+ expect(summary.stats.failures).toBe(0);
119
+ expect(summary.stats.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5, cached: 0 });
120
+ expect(summary.results[0].prompt.raw).toBe('Test prompt 1 < 2 he said "hello world"...');
121
+ expect(summary.results[0].prompt.label).toBe('Test prompt {{ var1 }} {{ var2 }}');
122
+ expect(summary.results[0].response?.output).toBe('Test output');
123
+ });
124
+ it('evaluate with vars as object', async () => {
125
+ const testSuite = {
126
+ providers: [mockApiProvider],
127
+ prompts: [toPrompt('Test prompt {{ var1.prop1 }} {{ var2 }}')],
128
+ tests: [
129
+ {
130
+ vars: { var1: { prop1: 'value1' }, var2: 'value2' },
131
+ },
132
+ ],
133
+ };
134
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
135
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(1);
136
+ expect(summary.stats.successes).toBe(1);
137
+ expect(summary.stats.failures).toBe(0);
138
+ expect(summary.stats.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5, cached: 0 });
139
+ expect(summary.results[0].prompt.raw).toBe('Test prompt value1 value2');
140
+ expect(summary.results[0].prompt.label).toBe('Test prompt {{ var1.prop1 }} {{ var2 }}');
141
+ expect(summary.results[0].response?.output).toBe('Test output');
142
+ });
143
+ it('evaluate with named prompt', async () => {
144
+ const testSuite = {
145
+ providers: [mockApiProvider],
146
+ prompts: [{ raw: 'Test prompt {{ var1 }} {{ var2 }}', label: 'test display name' }],
147
+ tests: [
148
+ {
149
+ vars: { var1: 'value1', var2: 'value2' },
150
+ },
151
+ ],
152
+ };
153
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
154
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(1);
155
+ expect(summary.stats.successes).toBe(1);
156
+ expect(summary.stats.failures).toBe(0);
157
+ expect(summary.stats.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5, cached: 0 });
158
+ expect(summary.results[0].prompt.raw).toBe('Test prompt value1 value2');
159
+ expect(summary.results[0].prompt.label).toBe('test display name');
160
+ expect(summary.results[0].response?.output).toBe('Test output');
161
+ });
162
+ it('evaluate with multiple vars', async () => {
163
+ const testSuite = {
164
+ providers: [mockApiProvider],
165
+ prompts: [toPrompt('Test prompt {{ var1 }} {{ var2 }}')],
166
+ tests: [
167
+ {
168
+ vars: { var1: ['value1', 'value3'], var2: ['value2', 'value4'] },
169
+ },
170
+ ],
171
+ };
172
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
173
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(4);
174
+ expect(summary.stats.successes).toBe(4);
175
+ expect(summary.stats.failures).toBe(0);
176
+ expect(summary.stats.tokenUsage).toEqual({ total: 40, prompt: 20, completion: 20, cached: 0 });
177
+ expect(summary.results[0].prompt.raw).toBe('Test prompt value1 value2');
178
+ expect(summary.results[0].prompt.label).toBe('Test prompt {{ var1 }} {{ var2 }}');
179
+ expect(summary.results[0].response?.output).toBe('Test output');
180
+ });
181
+ it('evaluate with multiple providers', async () => {
182
+ const testSuite = {
183
+ providers: [mockApiProvider, mockApiProvider],
184
+ prompts: [toPrompt('Test prompt {{ var1 }} {{ var2 }}')],
185
+ tests: [
186
+ {
187
+ vars: { var1: 'value1', var2: 'value2' },
188
+ },
189
+ ],
190
+ };
191
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
192
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(2);
193
+ expect(summary.stats.successes).toBe(2);
194
+ expect(summary.stats.failures).toBe(0);
195
+ expect(summary.stats.tokenUsage).toEqual({ total: 20, prompt: 10, completion: 10, cached: 0 });
196
+ expect(summary.results[0].prompt.raw).toBe('Test prompt value1 value2');
197
+ expect(summary.results[0].prompt.label).toBe('Test prompt {{ var1 }} {{ var2 }}');
198
+ expect(summary.results[0].response?.output).toBe('Test output');
199
+ });
200
+ it('evaluate without tests', async () => {
201
+ const testSuite = {
202
+ providers: [mockApiProvider],
203
+ prompts: [toPrompt('Test prompt')],
204
+ };
205
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
206
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(1);
207
+ expect(summary.stats.successes).toBe(1);
208
+ expect(summary.stats.failures).toBe(0);
209
+ expect(summary.stats.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5, cached: 0 });
210
+ expect(summary.results[0].prompt.raw).toBe('Test prompt');
211
+ expect(summary.results[0].prompt.label).toBe('Test prompt');
212
+ expect(summary.results[0].response?.output).toBe('Test output');
213
+ });
214
+ it('evaluate without tests with multiple providers', async () => {
215
+ const testSuite = {
216
+ providers: [mockApiProvider, mockApiProvider, mockApiProvider],
217
+ prompts: [toPrompt('Test prompt')],
218
+ };
219
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
220
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(3);
221
+ expect(summary.stats.successes).toBe(3);
222
+ expect(summary.stats.failures).toBe(0);
223
+ expect(summary.stats.tokenUsage).toEqual({ total: 30, prompt: 15, completion: 15, cached: 0 });
224
+ expect(summary.results[0].prompt.raw).toBe('Test prompt');
225
+ expect(summary.results[0].prompt.label).toBe('Test prompt');
226
+ expect(summary.results[0].response?.output).toBe('Test output');
227
+ });
228
+ it('evaluate with expected value matching output', async () => {
229
+ const testSuite = {
230
+ providers: [mockApiProvider],
231
+ prompts: [toPrompt('Test prompt')],
232
+ tests: [
233
+ {
234
+ assert: [
235
+ {
236
+ type: 'equals',
237
+ value: 'Test output',
238
+ },
239
+ ],
240
+ },
241
+ ],
242
+ };
243
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
244
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(1);
245
+ expect(summary.stats.successes).toBe(1);
246
+ expect(summary.stats.failures).toBe(0);
247
+ expect(summary.results[0].success).toBe(true);
248
+ expect(summary.results[0].response?.output).toBe('Test output');
249
+ });
250
+ it('evaluate with expected value not matching output', async () => {
251
+ const testSuite = {
252
+ providers: [mockApiProvider],
253
+ prompts: [toPrompt('Test prompt')],
254
+ tests: [
255
+ {
256
+ assert: [
257
+ {
258
+ type: 'equals',
259
+ value: 'Different output',
260
+ },
261
+ ],
262
+ },
263
+ ],
264
+ };
265
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
266
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(1);
267
+ expect(summary.stats.successes).toBe(0);
268
+ expect(summary.stats.failures).toBe(1);
269
+ expect(summary.results[0].success).toBe(false);
270
+ expect(summary.results[0].response?.output).toBe('Test output');
271
+ });
272
+ it('evaluate with fn: expected value', async () => {
273
+ const testSuite = {
274
+ providers: [mockApiProvider],
275
+ prompts: [toPrompt('Test prompt')],
276
+ tests: [
277
+ {
278
+ assert: [
279
+ {
280
+ type: 'javascript',
281
+ value: 'output === "Test output";',
282
+ },
283
+ ],
284
+ },
285
+ ],
286
+ };
287
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
288
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(1);
289
+ expect(summary.stats.successes).toBe(1);
290
+ expect(summary.stats.failures).toBe(0);
291
+ expect(summary.results[0].success).toBe(true);
292
+ expect(summary.results[0].response?.output).toBe('Test output');
293
+ });
294
+ it('evaluate with fn: expected value not matching output', async () => {
295
+ const testSuite = {
296
+ providers: [mockApiProvider],
297
+ prompts: [toPrompt('Test prompt')],
298
+ tests: [
299
+ {
300
+ assert: [
301
+ {
302
+ type: 'javascript',
303
+ value: 'output === "Different output";',
304
+ },
305
+ ],
306
+ },
307
+ ],
308
+ };
309
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
310
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(1);
311
+ expect(summary.stats.successes).toBe(0);
312
+ expect(summary.stats.failures).toBe(1);
313
+ expect(summary.results[0].success).toBe(false);
314
+ expect(summary.results[0].response?.output).toBe('Test output');
315
+ });
316
+ it('evaluate with grading expected value', async () => {
317
+ const testSuite = {
318
+ providers: [mockApiProvider],
319
+ prompts: [toPrompt('Test prompt')],
320
+ tests: [
321
+ {
322
+ assert: [
323
+ {
324
+ type: 'llm-rubric',
325
+ value: 'output is a test output',
326
+ },
327
+ ],
328
+ },
329
+ ],
330
+ defaultTest: {
331
+ options: {
332
+ provider: mockGradingApiProviderPasses,
333
+ },
334
+ },
335
+ };
336
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
337
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(1);
338
+ expect(summary.stats.successes).toBe(1);
339
+ expect(summary.stats.failures).toBe(0);
340
+ expect(summary.results[0].success).toBe(true);
341
+ expect(summary.results[0].response?.output).toBe('Test output');
342
+ });
343
+ it('evaluate with grading expected value does not pass', async () => {
344
+ const testSuite = {
345
+ providers: [mockApiProvider],
346
+ prompts: [toPrompt('Test prompt')],
347
+ tests: [
348
+ {
349
+ assert: [
350
+ {
351
+ type: 'llm-rubric',
352
+ value: 'output is a test output',
353
+ },
354
+ ],
355
+ },
356
+ ],
357
+ defaultTest: {
358
+ options: {
359
+ provider: mockGradingApiProviderFails,
360
+ },
361
+ },
362
+ };
363
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
364
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(1);
365
+ expect(summary.stats.successes).toBe(0);
366
+ expect(summary.stats.failures).toBe(1);
367
+ expect(summary.results[0].success).toBe(false);
368
+ expect(summary.results[0].response?.output).toBe('Test output');
369
+ });
370
+ it('evaluate with transform option - default test', async () => {
371
+ const testSuite = {
372
+ providers: [mockApiProvider],
373
+ prompts: [toPrompt('Test prompt')],
374
+ defaultTest: {
375
+ options: {
376
+ transform: 'output + " postprocessed"',
377
+ },
378
+ },
379
+ };
380
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
381
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(1);
382
+ expect(summary.stats.successes).toBe(1);
383
+ expect(summary.stats.failures).toBe(0);
384
+ expect(summary.results[0].response?.output).toBe('Test output postprocessed');
385
+ });
386
+ it('evaluate with transform option - single test', async () => {
387
+ const testSuite = {
388
+ providers: [mockApiProvider],
389
+ prompts: [toPrompt('Test prompt')],
390
+ tests: [
391
+ {
392
+ assert: [
393
+ {
394
+ type: 'equals',
395
+ value: 'Test output postprocessed',
396
+ },
397
+ ],
398
+ options: {
399
+ transform: 'output + " postprocessed"',
400
+ },
401
+ },
402
+ ],
403
+ };
404
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
405
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(1);
406
+ expect(summary.stats.successes).toBe(1);
407
+ expect(summary.stats.failures).toBe(0);
408
+ expect(summary.results[0].response?.output).toBe('Test output postprocessed');
409
+ });
410
+ it('evaluate with transform option - json provider', async () => {
411
+ const mockApiJsonProvider = {
412
+ id: jest.fn().mockReturnValue('test-provider-json'),
413
+ callApi: jest.fn().mockResolvedValue({
414
+ output: '{"output": "testing", "value": 123}',
415
+ tokenUsage: { total: 10, prompt: 5, completion: 5, cached: 0 },
416
+ }),
417
+ };
418
+ const testSuite = {
419
+ providers: [mockApiJsonProvider],
420
+ prompts: [toPrompt('Test prompt')],
421
+ tests: [
422
+ {
423
+ assert: [
424
+ {
425
+ type: 'equals',
426
+ value: '123',
427
+ },
428
+ ],
429
+ options: {
430
+ transform: `JSON.parse(output).value`,
431
+ },
432
+ },
433
+ ],
434
+ };
435
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
436
+ expect(mockApiJsonProvider.callApi).toHaveBeenCalledTimes(1);
437
+ expect(summary.stats.successes).toBe(1);
438
+ expect(summary.stats.failures).toBe(0);
439
+ expect(summary.results[0].response?.output).toBe(123);
440
+ });
441
+ it('evaluate with provider transform', async () => {
442
+ const mockApiProviderWithTransform = {
443
+ id: jest.fn().mockReturnValue('test-provider-transform'),
444
+ callApi: jest.fn().mockResolvedValue({
445
+ output: 'Original output',
446
+ tokenUsage: { total: 10, prompt: 5, completion: 5, cached: 0 },
447
+ }),
448
+ transform: '`Transformed: ${output}`',
449
+ };
450
+ const testSuite = {
451
+ providers: [mockApiProviderWithTransform],
452
+ prompts: [toPrompt('Test prompt')],
453
+ tests: [
454
+ {
455
+ assert: [
456
+ {
457
+ type: 'equals',
458
+ value: 'Transformed: Original output',
459
+ },
460
+ ],
461
+ options: {}, // No test transform, relying on provider's transform
462
+ },
463
+ ],
464
+ };
465
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
466
+ expect(mockApiProviderWithTransform.callApi).toHaveBeenCalledTimes(1);
467
+ expect(summary.stats.successes).toBe(1);
468
+ expect(summary.stats.failures).toBe(0);
469
+ expect(summary.results[0].response?.output).toBe('Transformed: Original output');
470
+ });
471
+ it('evaluate with providerPromptMap', async () => {
472
+ const testSuite = {
473
+ providers: [mockApiProvider],
474
+ prompts: [toPrompt('Test prompt 1'), toPrompt('Test prompt 2')],
475
+ providerPromptMap: {
476
+ 'test-provider': ['Test prompt 1'],
477
+ },
478
+ tests: [
479
+ {
480
+ vars: { var1: 'value1', var2: 'value2' },
481
+ },
482
+ ],
483
+ };
484
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
485
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(1);
486
+ expect(summary.stats.successes).toBe(1);
487
+ expect(summary.stats.failures).toBe(0);
488
+ expect(summary.stats.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5, cached: 0 });
489
+ expect(summary.results[0].prompt.raw).toBe('Test prompt 1');
490
+ expect(summary.results[0].prompt.label).toBe('Test prompt 1');
491
+ expect(summary.results[0].response?.output).toBe('Test output');
492
+ });
493
+ it('evaluate with allowed prompts filtering', async () => {
494
+ const mockApiProvider = {
495
+ id: jest.fn().mockReturnValue('test-provider'),
496
+ callApi: jest.fn().mockResolvedValue({
497
+ output: 'Test output',
498
+ tokenUsage: { total: 10, prompt: 5, completion: 5, cached: 0 },
499
+ }),
500
+ };
501
+ const testSuite = {
502
+ providers: [mockApiProvider],
503
+ prompts: [
504
+ { raw: 'Test prompt 1', label: 'prompt1' },
505
+ { raw: 'Test prompt 2', label: 'prompt2' },
506
+ { raw: 'Test prompt 3', label: 'group1:prompt3' },
507
+ ],
508
+ providerPromptMap: {
509
+ 'test-provider': ['prompt1', 'group1'],
510
+ },
511
+ tests: [
512
+ {
513
+ vars: { var1: 'value1', var2: 'value2' },
514
+ },
515
+ ],
516
+ };
517
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
518
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(2);
519
+ expect(summary).toMatchObject({
520
+ stats: {
521
+ successes: 2,
522
+ failures: 0,
523
+ },
524
+ results: [{ prompt: { label: 'prompt1' } }, { prompt: { label: 'group1:prompt3' } }],
525
+ });
526
+ });
527
+ it('evaluate with scenarios', async () => {
528
+ const mockApiProvider = {
529
+ id: jest.fn().mockReturnValue('test-provider'),
530
+ callApi: jest
531
+ .fn()
532
+ .mockResolvedValueOnce({
533
+ output: 'Hola mundo',
534
+ tokenUsage: { total: 10, prompt: 5, completion: 5, cached: 0 },
535
+ })
536
+ .mockResolvedValueOnce({
537
+ output: 'Bonjour le monde',
538
+ tokenUsage: { total: 10, prompt: 5, completion: 5, cached: 0 },
539
+ }),
540
+ };
541
+ const testSuite = {
542
+ providers: [mockApiProvider],
543
+ prompts: [toPrompt('Test prompt {{ language }}')],
544
+ scenarios: [
545
+ {
546
+ config: [
547
+ {
548
+ vars: {
549
+ language: 'Spanish',
550
+ expectedHelloWorld: 'Hola mundo',
551
+ },
552
+ },
553
+ {
554
+ vars: {
555
+ language: 'French',
556
+ expectedHelloWorld: 'Bonjour le monde',
557
+ },
558
+ },
559
+ ],
560
+ tests: [
561
+ {
562
+ assert: [
563
+ {
564
+ type: 'equals',
565
+ value: '{{expectedHelloWorld}}',
566
+ },
567
+ ],
568
+ },
569
+ ],
570
+ },
571
+ ],
572
+ };
573
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
574
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(2);
575
+ expect(summary.stats.successes).toBe(2);
576
+ expect(summary.stats.failures).toBe(0);
577
+ expect(summary.results[0].response?.output).toBe('Hola mundo');
578
+ expect(summary.results[1].response?.output).toBe('Bonjour le monde');
579
+ });
580
+ it('evaluate with scenarios and multiple vars', async () => {
581
+ const mockApiProvider = {
582
+ id: jest.fn().mockReturnValue('test-provider'),
583
+ callApi: jest
584
+ .fn()
585
+ .mockResolvedValueOnce({
586
+ output: 'Spanish Hola',
587
+ tokenUsage: { total: 10, prompt: 5, completion: 5, cached: 0 },
588
+ })
589
+ .mockResolvedValueOnce({
590
+ output: 'Spanish Bonjour',
591
+ tokenUsage: { total: 10, prompt: 5, completion: 5, cached: 0 },
592
+ })
593
+ .mockResolvedValueOnce({
594
+ output: 'French Hola',
595
+ tokenUsage: { total: 10, prompt: 5, completion: 5, cached: 0 },
596
+ })
597
+ .mockResolvedValueOnce({
598
+ output: 'French Bonjour',
599
+ tokenUsage: { total: 10, prompt: 5, completion: 5, cached: 0 },
600
+ }),
601
+ };
602
+ const testSuite = {
603
+ providers: [mockApiProvider],
604
+ prompts: [toPrompt('Test prompt {{ language }} {{ greeting }}')],
605
+ scenarios: [
606
+ {
607
+ config: [
608
+ {
609
+ vars: {
610
+ language: ['Spanish', 'French'],
611
+ greeting: ['Hola', 'Bonjour'],
612
+ },
613
+ },
614
+ ],
615
+ tests: [
616
+ {
617
+ assert: [
618
+ {
619
+ type: 'equals',
620
+ value: '{{language}} {{greeting}}',
621
+ },
622
+ ],
623
+ },
624
+ ],
625
+ },
626
+ ],
627
+ };
628
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
629
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(4);
630
+ expect(summary.stats.successes).toBe(4);
631
+ expect(summary.stats.failures).toBe(0);
632
+ expect(summary.results[0].response?.output).toBe('Spanish Hola');
633
+ expect(summary.results[1].response?.output).toBe('Spanish Bonjour');
634
+ expect(summary.results[2].response?.output).toBe('French Hola');
635
+ expect(summary.results[3].response?.output).toBe('French Bonjour');
636
+ });
637
+ it('evaluate with _conversation variable', async () => {
638
+ const mockApiProvider = {
639
+ id: jest.fn().mockReturnValue('test-provider'),
640
+ callApi: jest.fn().mockImplementation((prompt) => {
641
+ return Promise.resolve({
642
+ output: prompt,
643
+ tokenUsage: { total: 10, prompt: 5, completion: 5, cached: 0 },
644
+ });
645
+ }),
646
+ };
647
+ const testSuite = {
648
+ providers: [mockApiProvider],
649
+ prompts: [toPrompt('{{ var1 }} {{ _conversation[0].output }}')],
650
+ tests: [
651
+ {
652
+ vars: { var1: 'First run' },
653
+ },
654
+ {
655
+ vars: { var1: 'Second run' },
656
+ },
657
+ ],
658
+ };
659
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
660
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(2);
661
+ expect(summary.stats.successes).toBe(2);
662
+ expect(summary.stats.failures).toBe(0);
663
+ expect(summary.results[0].response?.output).toBe('First run ');
664
+ expect(summary.results[1].response?.output).toBe('Second run First run ');
665
+ });
666
+ it('evaluate with labeled and unlabeled providers and providerPromptMap', async () => {
667
+ const mockLabeledProvider = {
668
+ id: () => 'labeled-provider-id',
669
+ label: 'Labeled Provider',
670
+ callApi: jest.fn().mockResolvedValue({
671
+ output: 'Labeled Provider Output',
672
+ tokenUsage: { total: 10, prompt: 5, completion: 5, cached: 0 },
673
+ }),
674
+ };
675
+ const mockUnlabeledProvider = {
676
+ id: () => 'unlabeled-provider-id',
677
+ callApi: jest.fn().mockResolvedValue({
678
+ output: 'Unlabeled Provider Output',
679
+ tokenUsage: { total: 10, prompt: 5, completion: 5, cached: 0 },
680
+ }),
681
+ };
682
+ const testSuite = {
683
+ providers: [mockLabeledProvider, mockUnlabeledProvider],
684
+ prompts: [
685
+ {
686
+ raw: 'Prompt 1',
687
+ label: 'prompt1',
688
+ },
689
+ {
690
+ raw: 'Prompt 2',
691
+ label: 'prompt2',
692
+ },
693
+ ],
694
+ providerPromptMap: {
695
+ 'Labeled Provider': ['prompt1'],
696
+ 'unlabeled-provider-id': ['prompt2'],
697
+ },
698
+ };
699
+ await expect((0, evaluator_1.evaluate)(testSuite, {})).resolves.toEqual(expect.objectContaining({
700
+ stats: expect.objectContaining({
701
+ successes: 2,
702
+ failures: 0,
703
+ }),
704
+ results: [
705
+ expect.objectContaining({
706
+ provider: expect.objectContaining({
707
+ id: 'labeled-provider-id',
708
+ label: 'Labeled Provider',
709
+ }),
710
+ response: expect.objectContaining({
711
+ output: 'Labeled Provider Output',
712
+ }),
713
+ }),
714
+ expect.objectContaining({
715
+ provider: expect.objectContaining({
716
+ id: 'unlabeled-provider-id',
717
+ label: undefined,
718
+ }),
719
+ response: expect.objectContaining({
720
+ output: 'Unlabeled Provider Output',
721
+ }),
722
+ }),
723
+ ],
724
+ table: expect.objectContaining({
725
+ head: expect.objectContaining({
726
+ prompts: [
727
+ expect.objectContaining({
728
+ provider: 'Labeled Provider',
729
+ }),
730
+ expect.objectContaining({
731
+ provider: 'unlabeled-provider-id',
732
+ }),
733
+ ],
734
+ }),
735
+ }),
736
+ }));
737
+ expect(mockLabeledProvider.callApi).toHaveBeenCalledTimes(1);
738
+ expect(mockUnlabeledProvider.callApi).toHaveBeenCalledTimes(1);
739
+ });
740
+ it('should use the options from the test if they exist', async () => {
741
+ const testSuite = {
742
+ providers: [mockApiProvider],
743
+ prompts: [toPrompt('Test prompt')],
744
+ tests: [
745
+ {
746
+ vars: { var1: 'value1', var2: 'value2' },
747
+ options: {
748
+ transform: 'output + " postprocessed"',
749
+ },
750
+ },
751
+ ],
752
+ };
753
+ const summary = await (0, evaluator_1.evaluate)(testSuite, {});
754
+ expect(mockApiProvider.callApi).toHaveBeenCalledTimes(1);
755
+ expect(summary.stats.successes).toBe(1);
756
+ expect(summary.stats.failures).toBe(0);
757
+ expect(summary.results[0].response?.output).toBe('Test output postprocessed');
758
+ });
759
+ });
760
+ describe('renderPrompt', () => {
761
+ it('should render a prompt with a single variable', async () => {
762
+ const prompt = toPrompt('Test prompt {{ var1 }}');
763
+ const renderedPrompt = await (0, evaluator_1.renderPrompt)(prompt, { var1: 'value1' }, {});
764
+ expect(renderedPrompt).toBe('Test prompt value1');
765
+ });
766
+ it('should render a JSON prompt', async () => {
767
+ const prompt = toPrompt('[{"text": "Test prompt "}, {"text": "{{ var1 }}"}]');
768
+ const renderedPrompt = await (0, evaluator_1.renderPrompt)(prompt, { var1: 'value1' }, {});
769
+ expect(renderedPrompt).toBe(JSON.stringify(JSON.parse('[{"text":"Test prompt "},{"text":"value1"}]'), null, 2));
770
+ });
771
+ it('should render a JSON prompt and escape the var string', async () => {
772
+ const prompt = toPrompt('[{"text": "Test prompt "}, {"text": "{{ var1 }}"}]');
773
+ const renderedPrompt = await (0, evaluator_1.renderPrompt)(prompt, { var1: 'He said "hello world!"' }, {});
774
+ expect(renderedPrompt).toBe(JSON.stringify(JSON.parse('[{"text":"Test prompt "},{"text":"He said \\"hello world!\\""}]'), null, 2));
775
+ });
776
+ it('should render a JSON prompt with nested JSON', async () => {
777
+ const prompt = toPrompt('[{"text": "Test prompt "}, {"text": "{{ var1 }}"}]');
778
+ const renderedPrompt = await (0, evaluator_1.renderPrompt)(prompt, { var1: '{"nested": "value1"}' }, {});
779
+ expect(renderedPrompt).toBe(JSON.stringify(JSON.parse('[{"text":"Test prompt "},{"text":"{\\"nested\\": \\"value1\\"}"}]'), null, 2));
780
+ });
781
+ it('should load external yaml files in renderPrompt', async () => {
782
+ const prompt = toPrompt('Test prompt with {{ var1 }}');
783
+ const vars = { var1: 'file://test.txt' };
784
+ const evaluateOptions = {};
785
+ // Mock fs.readFileSync to simulate loading a YAML file
786
+ jest.spyOn(fs, 'readFileSync').mockReturnValueOnce('loaded from file');
787
+ const renderedPrompt = await (0, evaluator_1.renderPrompt)(prompt, vars, evaluateOptions);
788
+ expect(fs.readFileSync).toHaveBeenCalledWith(expect.stringContaining('test.txt'), 'utf8');
789
+ expect(renderedPrompt).toBe('Test prompt with loaded from file');
790
+ });
791
+ it('should load external js files in renderPrompt and execute the exported function', async () => {
792
+ const prompt = toPrompt('Test prompt with {{ var1 }}');
793
+ const vars = { var1: 'file:///path/to/testFunction.js' };
794
+ const evaluateOptions = {};
795
+ jest.doMock(path.resolve('/path/to/testFunction.js'), () => (varName, prompt, vars) => ({ output: `Dynamic value for ${varName}` }), { virtual: true });
796
+ const renderedPrompt = await (0, evaluator_1.renderPrompt)(prompt, vars, evaluateOptions);
797
+ expect(renderedPrompt).toBe('Test prompt with Dynamic value for var1');
798
+ });
799
+ it('should load external json files in renderPrompt and parse the JSON content', async () => {
800
+ const prompt = toPrompt('Test prompt with {{ var1 }}');
801
+ const vars = { var1: 'file:///path/to/testData.json' };
802
+ const evaluateOptions = {};
803
+ jest.spyOn(fs, 'readFileSync').mockReturnValueOnce(JSON.stringify({ key: 'valueFromJson' }));
804
+ const renderedPrompt = await (0, evaluator_1.renderPrompt)(prompt, vars, evaluateOptions);
805
+ expect(fs.readFileSync).toHaveBeenCalledWith(expect.stringContaining('testData.json'), 'utf8');
806
+ expect(renderedPrompt).toBe('Test prompt with {"key":"valueFromJson"}');
807
+ });
808
+ it('should load external yaml files in renderPrompt and parse the YAML content', async () => {
809
+ const prompt = toPrompt('Test prompt with {{ var1 }}');
810
+ const vars = { var1: 'file:///path/to/testData.yaml' };
811
+ const evaluateOptions = {};
812
+ jest.spyOn(fs, 'readFileSync').mockReturnValueOnce('key: valueFromYaml');
813
+ const renderedPrompt = await (0, evaluator_1.renderPrompt)(prompt, vars, evaluateOptions);
814
+ expect(fs.readFileSync).toHaveBeenCalledWith(expect.stringContaining('testData.yaml'), 'utf8');
815
+ expect(renderedPrompt).toBe('Test prompt with {"key":"valueFromYaml"}');
816
+ });
817
+ });
818
+ describe('resolveVariables', () => {
819
+ it('should replace placeholders with corresponding variable values', () => {
820
+ const variables = { final: '{{ my_greeting }}, {{name}}!', my_greeting: 'Hello', name: 'John' };
821
+ const expected = { final: 'Hello, John!', my_greeting: 'Hello', name: 'John' };
822
+ expect((0, evaluator_1.resolveVariables)(variables)).toEqual(expected);
823
+ });
824
+ it('should handle nested variable substitutions', () => {
825
+ const variables = { first: '{{second}}', second: '{{third}}', third: 'value' };
826
+ const expected = { first: 'value', second: 'value', third: 'value' };
827
+ expect((0, evaluator_1.resolveVariables)(variables)).toEqual(expected);
828
+ });
829
+ it('should not modify variables without placeholders', () => {
830
+ const variables = { greeting: 'Hello, world!', name: 'John' };
831
+ const expected = { greeting: 'Hello, world!', name: 'John' };
832
+ expect((0, evaluator_1.resolveVariables)(variables)).toEqual(expected);
833
+ });
834
+ it('should not fail if a variable is not found', () => {
835
+ const variables = { greeting: 'Hello, {{name}}!' };
836
+ expect((0, evaluator_1.resolveVariables)(variables)).toEqual({ greeting: 'Hello, {{name}}!' });
837
+ });
838
+ it('should not fail for unresolved placeholders', () => {
839
+ const variables = { greeting: 'Hello, {{name}}!', name: '{{unknown}}' };
840
+ expect((0, evaluator_1.resolveVariables)(variables)).toEqual({
841
+ greeting: 'Hello, {{unknown}}!',
842
+ name: '{{unknown}}',
843
+ });
844
+ });
845
+ });
846
+ describe('generateVarCombinations', () => {
847
+ it('should generate combinations for simple variables', () => {
848
+ const vars = { language: 'English', greeting: 'Hello' };
849
+ const expected = [{ language: 'English', greeting: 'Hello' }];
850
+ expect((0, evaluator_1.generateVarCombinations)(vars)).toEqual(expected);
851
+ });
852
+ it('should generate combinations for array variables', () => {
853
+ const vars = { language: ['English', 'French'], greeting: 'Hello' };
854
+ const expected = [
855
+ { language: 'English', greeting: 'Hello' },
856
+ { language: 'French', greeting: 'Hello' },
857
+ ];
858
+ expect((0, evaluator_1.generateVarCombinations)(vars)).toEqual(expected);
859
+ });
860
+ it('should handle file paths and expand them into combinations', () => {
861
+ const vars = { language: 'English', greeting: 'file:///path/to/greetings/*.txt' };
862
+ jest.spyOn(glob_1.default, 'globSync').mockReturnValue(['greeting1.txt', 'greeting2.txt']);
863
+ const expected = [
864
+ { language: 'English', greeting: 'file://greeting1.txt' },
865
+ { language: 'English', greeting: 'file://greeting2.txt' },
866
+ ];
867
+ expect((0, evaluator_1.generateVarCombinations)(vars)).toEqual(expected);
868
+ });
869
+ it('should correctly handle nested array variables', () => {
870
+ const vars = {
871
+ options: [
872
+ ['opt1', 'opt2'],
873
+ ['opt3', 'opt4'],
874
+ ],
875
+ };
876
+ const expected = [
877
+ {
878
+ options: [
879
+ ['opt1', 'opt2'],
880
+ ['opt3', 'opt4'],
881
+ ],
882
+ },
883
+ ];
884
+ expect((0, evaluator_1.generateVarCombinations)(vars)).toEqual(expected);
885
+ });
886
+ it('should return an empty array for empty input', () => {
887
+ const vars = {};
888
+ const expected = [{}];
889
+ expect((0, evaluator_1.generateVarCombinations)(vars)).toEqual(expected);
890
+ });
891
+ });
892
+ describe('isAllowedPrompt', () => {
893
+ const prompt1 = {
894
+ label: 'prompt1',
895
+ raw: '',
896
+ };
897
+ const prompt2 = {
898
+ label: 'group1:prompt2',
899
+ raw: '',
900
+ };
901
+ const prompt3 = {
902
+ label: 'group2:prompt3',
903
+ raw: '',
904
+ };
905
+ it('should return true if allowedPrompts is undefined', () => {
906
+ expect((0, evaluator_1.isAllowedPrompt)(prompt1, undefined)).toBe(true);
907
+ });
908
+ it('should return true if allowedPrompts includes the prompt label', () => {
909
+ expect((0, evaluator_1.isAllowedPrompt)(prompt1, ['prompt1', 'prompt2'])).toBe(true);
910
+ });
911
+ it('should return true if allowedPrompts includes a label that matches the start of the prompt label followed by a colon', () => {
912
+ expect((0, evaluator_1.isAllowedPrompt)(prompt2, ['group1'])).toBe(true);
913
+ });
914
+ it('should return false if allowedPrompts does not include the prompt label or any matching start label with a colon', () => {
915
+ expect((0, evaluator_1.isAllowedPrompt)(prompt3, ['group1', 'prompt2'])).toBe(false);
916
+ });
917
+ // TODO: What should the expected behavior of this test be?
918
+ it('should return false if allowedPrompts is an empty array', () => {
919
+ expect((0, evaluator_1.isAllowedPrompt)(prompt1, [])).toBe(false);
920
+ });
921
+ });
922
+ //# sourceMappingURL=evaluator.test.js.map