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,883 @@
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 child_process_1 = __importDefault(require("child_process"));
30
+ const fs = __importStar(require("fs"));
31
+ const node_fetch_1 = __importDefault(require("node-fetch"));
32
+ const path = __importStar(require("path"));
33
+ const stream_1 = __importDefault(require("stream"));
34
+ const cache_1 = require("../src/cache");
35
+ const esm_1 = require("../src/esm");
36
+ const providers_1 = require("../src/providers");
37
+ const anthropic_1 = require("../src/providers/anthropic");
38
+ const azureopenai_1 = require("../src/providers/azureopenai");
39
+ const bedrock_1 = require("../src/providers/bedrock");
40
+ const cloudflare_ai_1 = require("../src/providers/cloudflare-ai");
41
+ const huggingface_1 = require("../src/providers/huggingface");
42
+ const llama_1 = require("../src/providers/llama");
43
+ const ollama_1 = require("../src/providers/ollama");
44
+ const openai_1 = require("../src/providers/openai");
45
+ const replicate_1 = require("../src/providers/replicate");
46
+ const scriptCompletion_1 = require("../src/providers/scriptCompletion");
47
+ const vertex_1 = require("../src/providers/vertex");
48
+ const voyage_1 = require("../src/providers/voyage");
49
+ const webhook_1 = require("../src/providers/webhook");
50
+ const iterative_1 = __importDefault(require("../src/redteam/providers/iterative"));
51
+ const iterativeImage_1 = __importDefault(require("../src/redteam/providers/iterativeImage"));
52
+ jest.mock('fs', () => ({
53
+ readFileSync: jest.fn(),
54
+ writeFileSync: jest.fn(),
55
+ statSync: jest.fn(),
56
+ readdirSync: jest.fn(),
57
+ existsSync: jest.fn(),
58
+ mkdirSync: jest.fn(),
59
+ promises: {
60
+ readFile: jest.fn(),
61
+ },
62
+ }));
63
+ jest.mock('glob', () => ({
64
+ globSync: jest.fn(),
65
+ }));
66
+ jest.mock('node-fetch', () => jest.fn());
67
+ jest.mock('proxy-agent', () => ({
68
+ ProxyAgent: jest.fn().mockImplementation(() => ({})),
69
+ }));
70
+ jest.mock('../src/esm', () => ({
71
+ ...jest.requireActual('../src/esm'),
72
+ importModule: jest.fn(),
73
+ }));
74
+ jest.mock('fs', () => ({
75
+ readFileSync: jest.fn(),
76
+ existsSync: jest.fn(),
77
+ mkdirSync: jest.fn(),
78
+ }));
79
+ jest.mock('glob', () => ({
80
+ globSync: jest.fn(),
81
+ }));
82
+ jest.mock('../src/database', () => ({
83
+ getDb: jest.fn(),
84
+ }));
85
+ describe('call provider apis', () => {
86
+ afterEach(async () => {
87
+ jest.clearAllMocks();
88
+ await (0, cache_1.clearCache)();
89
+ });
90
+ it('OpenAiCompletionProvider callApi', async () => {
91
+ const mockResponse = {
92
+ text: jest.fn().mockResolvedValue(JSON.stringify({
93
+ choices: [{ text: 'Test output' }],
94
+ usage: { total_tokens: 10, prompt_tokens: 5, completion_tokens: 5 },
95
+ })),
96
+ };
97
+ jest.mocked(node_fetch_1.default).mockResolvedValue(mockResponse);
98
+ const provider = new openai_1.OpenAiCompletionProvider('text-davinci-003');
99
+ const result = await provider.callApi('Test prompt');
100
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
101
+ expect(result.output).toBe('Test output');
102
+ expect(result.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5 });
103
+ });
104
+ it('OpenAiChatCompletionProvider callApi', async () => {
105
+ const mockResponse = {
106
+ text: jest.fn().mockResolvedValue(JSON.stringify({
107
+ choices: [{ message: { content: 'Test output' } }],
108
+ usage: { total_tokens: 10, prompt_tokens: 5, completion_tokens: 5 },
109
+ })),
110
+ ok: true,
111
+ };
112
+ jest.mocked(node_fetch_1.default).mockResolvedValue(mockResponse);
113
+ const provider = new openai_1.OpenAiChatCompletionProvider('gpt-3.5-turbo');
114
+ const result = await provider.callApi(JSON.stringify([{ role: 'user', content: 'Test prompt' }]));
115
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
116
+ expect(result.output).toBe('Test output');
117
+ expect(result.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5 });
118
+ });
119
+ it('OpenAiChatCompletionProvider callApi with caching', async () => {
120
+ const mockResponse = {
121
+ text: jest.fn().mockResolvedValue(JSON.stringify({
122
+ choices: [{ message: { content: 'Test output 2' } }],
123
+ usage: { total_tokens: 10, prompt_tokens: 5, completion_tokens: 5 },
124
+ })),
125
+ ok: true,
126
+ };
127
+ jest.mocked(node_fetch_1.default).mockResolvedValue(mockResponse);
128
+ const provider = new openai_1.OpenAiChatCompletionProvider('gpt-3.5-turbo');
129
+ const result = await provider.callApi(JSON.stringify([{ role: 'user', content: 'Test prompt 2' }]));
130
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
131
+ expect(result.output).toBe('Test output 2');
132
+ expect(result.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5 });
133
+ const result2 = await provider.callApi(JSON.stringify([{ role: 'user', content: 'Test prompt 2' }]));
134
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
135
+ expect(result2.output).toBe('Test output 2');
136
+ expect(result2.tokenUsage).toEqual({ total: 10, cached: 10 });
137
+ });
138
+ it('OpenAiChatCompletionProvider callApi with cache disabled', async () => {
139
+ const mockResponse = {
140
+ text: jest.fn().mockResolvedValue(JSON.stringify({
141
+ choices: [{ message: { content: 'Test output' } }],
142
+ usage: { total_tokens: 10, prompt_tokens: 5, completion_tokens: 5 },
143
+ })),
144
+ ok: true,
145
+ };
146
+ jest.mocked(node_fetch_1.default).mockResolvedValue(mockResponse);
147
+ const provider = new openai_1.OpenAiChatCompletionProvider('gpt-3.5-turbo');
148
+ const result = await provider.callApi(JSON.stringify([{ role: 'user', content: 'Test prompt' }]));
149
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
150
+ expect(result.output).toBe('Test output');
151
+ expect(result.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5 });
152
+ (0, cache_1.disableCache)();
153
+ const result2 = await provider.callApi(JSON.stringify([{ role: 'user', content: 'Test prompt' }]));
154
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(2);
155
+ expect(result2.output).toBe('Test output');
156
+ expect(result2.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5 });
157
+ (0, cache_1.enableCache)();
158
+ });
159
+ it('OpenAiChatCompletionProvider constructor with config', async () => {
160
+ const config = {
161
+ temperature: 3.1415926,
162
+ max_tokens: 201,
163
+ };
164
+ const provider = new openai_1.OpenAiChatCompletionProvider('gpt-3.5-turbo', { config });
165
+ const prompt = 'Test prompt';
166
+ await provider.callApi(prompt);
167
+ expect(node_fetch_1.default).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
168
+ body: expect.stringMatching(`temperature\":3.1415926`),
169
+ }));
170
+ expect(provider.config.temperature).toBe(config.temperature);
171
+ expect(provider.config.max_tokens).toBe(config.max_tokens);
172
+ });
173
+ it('AzureOpenAiCompletionProvider callApi', async () => {
174
+ const mockResponse = {
175
+ text: jest.fn().mockResolvedValue(JSON.stringify({
176
+ choices: [{ text: 'Test output' }],
177
+ usage: { total_tokens: 10, prompt_tokens: 5, completion_tokens: 5 },
178
+ })),
179
+ };
180
+ jest.mocked(node_fetch_1.default).mockResolvedValue(mockResponse);
181
+ const provider = new azureopenai_1.AzureOpenAiCompletionProvider('text-davinci-003');
182
+ const result = await provider.callApi('Test prompt');
183
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
184
+ expect(result.output).toBe('Test output');
185
+ expect(result.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5 });
186
+ });
187
+ it('AzureOpenAiChatCompletionProvider callApi', async () => {
188
+ const mockResponse = {
189
+ text: jest.fn().mockResolvedValue(JSON.stringify({
190
+ choices: [{ message: { content: 'Test output' } }],
191
+ usage: { total_tokens: 10, prompt_tokens: 5, completion_tokens: 5 },
192
+ })),
193
+ };
194
+ jest.mocked(node_fetch_1.default).mockResolvedValue(mockResponse);
195
+ const provider = new azureopenai_1.AzureOpenAiChatCompletionProvider('gpt-3.5-turbo');
196
+ const result = await provider.callApi(JSON.stringify([{ role: 'user', content: 'Test prompt' }]));
197
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
198
+ expect(result.output).toBe('Test output');
199
+ expect(result.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5 });
200
+ });
201
+ it('AzureOpenAiChatCompletionProvider callApi with dataSources', async () => {
202
+ const dataSources = [
203
+ {
204
+ type: 'AzureCognitiveSearch',
205
+ endpoint: 'https://search.windows.net',
206
+ indexName: 'search-test',
207
+ semanticConfiguration: 'default',
208
+ queryType: 'vectorSimpleHybrid',
209
+ },
210
+ ];
211
+ const mockResponse = {
212
+ text: jest.fn().mockResolvedValue(JSON.stringify({
213
+ choices: [
214
+ { message: { role: 'system', content: 'System prompt' } },
215
+ { message: { role: 'user', content: 'Test prompt' } },
216
+ { message: { role: 'assistant', content: 'Test response' } },
217
+ ],
218
+ usage: { total_tokens: 10, prompt_tokens: 5, completion_tokens: 5 },
219
+ })),
220
+ };
221
+ jest.mocked(node_fetch_1.default).mockResolvedValue(mockResponse);
222
+ const provider = new azureopenai_1.AzureOpenAiChatCompletionProvider('gpt-3.5-turbo', {
223
+ config: { dataSources },
224
+ });
225
+ const result = await provider.callApi(JSON.stringify([
226
+ { role: 'system', content: 'System prompt' },
227
+ { role: 'user', content: 'Test prompt' },
228
+ ]));
229
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
230
+ expect(result.output).toBe('Test response');
231
+ expect(result.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5 });
232
+ });
233
+ it('AzureOpenAiChatCompletionProvider callApi with cache disabled', async () => {
234
+ (0, cache_1.disableCache)();
235
+ const mockResponse = {
236
+ text: jest.fn().mockResolvedValue(JSON.stringify({
237
+ choices: [{ message: { content: 'Test output' } }],
238
+ usage: { total_tokens: 10, prompt_tokens: 5, completion_tokens: 5 },
239
+ })),
240
+ };
241
+ jest.mocked(node_fetch_1.default).mockResolvedValue(mockResponse);
242
+ const provider = new azureopenai_1.AzureOpenAiChatCompletionProvider('gpt-3.5-turbo');
243
+ const result = await provider.callApi(JSON.stringify([{ role: 'user', content: 'Test prompt' }]));
244
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
245
+ expect(result.output).toBe('Test output');
246
+ expect(result.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5 });
247
+ (0, cache_1.enableCache)();
248
+ });
249
+ it('LlamaProvider callApi', async () => {
250
+ const mockResponse = {
251
+ text: jest.fn().mockResolvedValue(JSON.stringify({
252
+ content: 'Test output',
253
+ })),
254
+ };
255
+ jest.mocked(node_fetch_1.default).mockResolvedValue(mockResponse);
256
+ const provider = new llama_1.LlamaProvider('llama.cpp');
257
+ const result = await provider.callApi('Test prompt');
258
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
259
+ expect(result.output).toBe('Test output');
260
+ });
261
+ it('OllamaCompletionProvider callApi', async () => {
262
+ const mockResponse = {
263
+ text: jest.fn()
264
+ .mockResolvedValue(`{"model":"llama2:13b","created_at":"2023-08-08T21:50:34.898068Z","response":"Gre","done":false}
265
+ {"model":"llama2:13b","created_at":"2023-08-08T21:50:34.929199Z","response":"at","done":false}
266
+ {"model":"llama2:13b","created_at":"2023-08-08T21:50:34.959989Z","response":" question","done":false}
267
+ {"model":"llama2:13b","created_at":"2023-08-08T21:50:34.992117Z","response":"!","done":false}
268
+ {"model":"llama2:13b","created_at":"2023-08-08T21:50:35.023658Z","response":" The","done":false}
269
+ {"model":"llama2:13b","created_at":"2023-08-08T21:50:35.0551Z","response":" sky","done":false}
270
+ {"model":"llama2:13b","created_at":"2023-08-08T21:50:35.086103Z","response":" appears","done":false}
271
+ {"model":"llama2:13b","created_at":"2023-08-08T21:50:35.117166Z","response":" blue","done":false}
272
+ {"model":"llama2:13b","created_at":"2023-08-08T21:50:41.695299Z","done":true,"context":[1,29871,1,13,9314],"total_duration":10411943458,"load_duration":458333,"sample_count":217,"sample_duration":154566000,"prompt_eval_count":11,"prompt_eval_duration":3334582000,"eval_count":216,"eval_duration":6905134000}`),
273
+ };
274
+ jest.mocked(node_fetch_1.default).mockResolvedValue(mockResponse);
275
+ const provider = new ollama_1.OllamaCompletionProvider('llama');
276
+ const result = await provider.callApi('Test prompt');
277
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
278
+ expect(result.output).toBe('Great question! The sky appears blue');
279
+ });
280
+ it('OllamaChatProvider callApi', async () => {
281
+ const mockResponse = {
282
+ text: jest.fn()
283
+ .mockResolvedValue(`{"model":"orca-mini","created_at":"2023-12-16T01:46:19.263682972Z","message":{"role":"assistant","content":" Because","images":null},"done":false}
284
+ {"model":"orca-mini","created_at":"2023-12-16T01:46:19.275143974Z","message":{"role":"assistant","content":" of","images":null},"done":false}
285
+ {"model":"orca-mini","created_at":"2023-12-16T01:46:19.288137727Z","message":{"role":"assistant","content":" Ray","images":null},"done":false}
286
+ {"model":"orca-mini","created_at":"2023-12-16T01:46:19.301139709Z","message":{"role":"assistant","content":"leigh","images":null},"done":false}
287
+ {"model":"orca-mini","created_at":"2023-12-16T01:46:19.311364699Z","message":{"role":"assistant","content":" scattering","images":null},"done":false}
288
+ {"model":"orca-mini","created_at":"2023-12-16T01:46:19.324309782Z","message":{"role":"assistant","content":".","images":null},"done":false}
289
+ {"model":"orca-mini","created_at":"2023-12-16T01:46:19.337165395Z","done":true,"total_duration":1486443841,"load_duration":1280794143,"prompt_eval_count":35,"prompt_eval_duration":142384000,"eval_count":6,"eval_duration":61912000}`),
290
+ };
291
+ jest.mocked(node_fetch_1.default).mockResolvedValue(mockResponse);
292
+ const provider = new ollama_1.OllamaChatProvider('llama');
293
+ const result = await provider.callApi('Test prompt');
294
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
295
+ expect(result.output).toBe(' Because of Rayleigh scattering.');
296
+ });
297
+ it('WebhookProvider callApi', async () => {
298
+ const mockResponse = {
299
+ text: jest.fn().mockResolvedValue(JSON.stringify({
300
+ output: 'Test output',
301
+ })),
302
+ };
303
+ jest.mocked(node_fetch_1.default).mockResolvedValue(mockResponse);
304
+ const provider = new webhook_1.WebhookProvider('http://example.com/webhook');
305
+ const result = await provider.callApi('Test prompt');
306
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
307
+ expect(result.output).toBe('Test output');
308
+ });
309
+ describe.each([
310
+ ['Array format', [{ generated_text: 'Test output' }]], // Array format
311
+ ['Object format', { generated_text: 'Test output' }], // Object format
312
+ ])('HuggingfaceTextGenerationProvider callApi with %s', (format, mockedData) => {
313
+ it('returns expected output', async () => {
314
+ const mockResponse = {
315
+ text: jest.fn().mockResolvedValue(JSON.stringify(mockedData)),
316
+ };
317
+ jest.mocked(node_fetch_1.default).mockResolvedValue(mockResponse);
318
+ const provider = new huggingface_1.HuggingfaceTextGenerationProvider('gpt2');
319
+ const result = await provider.callApi('Test prompt');
320
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
321
+ expect(result.output).toBe('Test output');
322
+ });
323
+ });
324
+ it('HuggingfaceFeatureExtractionProvider callEmbeddingApi', async () => {
325
+ const mockResponse = {
326
+ text: jest.fn().mockResolvedValue(JSON.stringify([0.1, 0.2, 0.3, 0.4, 0.5])),
327
+ };
328
+ jest.mocked(node_fetch_1.default).mockResolvedValue(mockResponse);
329
+ const provider = new huggingface_1.HuggingfaceFeatureExtractionProvider('distilbert-base-uncased');
330
+ const result = await provider.callEmbeddingApi('Test text');
331
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
332
+ expect(result.embedding).toEqual([0.1, 0.2, 0.3, 0.4, 0.5]);
333
+ });
334
+ it('HuggingfaceTextClassificationProvider callClassificationApi', async () => {
335
+ const mockClassification = [
336
+ [
337
+ {
338
+ label: 'nothate',
339
+ score: 0.9,
340
+ },
341
+ {
342
+ label: 'hate',
343
+ score: 0.1,
344
+ },
345
+ ],
346
+ ];
347
+ const mockResponse = {
348
+ text: jest.fn().mockResolvedValue(JSON.stringify(mockClassification)),
349
+ };
350
+ jest.mocked(node_fetch_1.default).mockResolvedValue(mockResponse);
351
+ const provider = new huggingface_1.HuggingfaceTextClassificationProvider('foo');
352
+ const result = await provider.callClassificationApi('Test text');
353
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
354
+ expect(result.classification).toEqual({
355
+ nothate: 0.9,
356
+ hate: 0.1,
357
+ });
358
+ });
359
+ describe('CloudflareAi', () => {
360
+ beforeAll(() => {
361
+ (0, cache_1.enableCache)();
362
+ });
363
+ const fetchMock = jest.mocked(node_fetch_1.default);
364
+ const cloudflareMinimumConfig = {
365
+ accountId: 'testAccountId',
366
+ apiKey: 'testApiKey',
367
+ };
368
+ const testModelName = '@cf/meta/llama-2-7b-chat-fp16';
369
+ // Token usage is not implemented for cloudflare so this is the default that
370
+ // is returned
371
+ const tokenUsageDefaultResponse = {
372
+ total: undefined,
373
+ prompt: undefined,
374
+ completion: undefined,
375
+ };
376
+ describe('CloudflareAiCompletionProvider', () => {
377
+ it('callApi with caching enabled', async () => {
378
+ const PROMPT = 'Test prompt for caching';
379
+ const provider = new cloudflare_ai_1.CloudflareAiCompletionProvider(testModelName, {
380
+ config: cloudflareMinimumConfig,
381
+ });
382
+ const responsePayload = {
383
+ success: true,
384
+ errors: [],
385
+ messages: [],
386
+ result: {
387
+ response: 'Test text output',
388
+ },
389
+ };
390
+ const mockResponse = {
391
+ text: jest.fn().mockResolvedValue(JSON.stringify(responsePayload)),
392
+ ok: true,
393
+ };
394
+ fetchMock.mockResolvedValue(mockResponse);
395
+ const result = await provider.callApi(PROMPT);
396
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
397
+ expect(result.output).toBe(responsePayload.result.response);
398
+ expect(result.tokenUsage).toEqual(tokenUsageDefaultResponse);
399
+ const resultFromCache = await provider.callApi(PROMPT);
400
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
401
+ expect(resultFromCache.output).toBe(responsePayload.result.response);
402
+ expect(resultFromCache.tokenUsage).toEqual(tokenUsageDefaultResponse);
403
+ });
404
+ it('callApi with caching disabled', async () => {
405
+ const PROMPT = 'test prompt without caching';
406
+ try {
407
+ (0, cache_1.disableCache)();
408
+ const provider = new cloudflare_ai_1.CloudflareAiCompletionProvider(testModelName, {
409
+ config: cloudflareMinimumConfig,
410
+ });
411
+ const responsePayload = {
412
+ success: true,
413
+ errors: [],
414
+ messages: [],
415
+ result: {
416
+ response: 'Test text output',
417
+ },
418
+ };
419
+ const mockResponse = {
420
+ text: jest.fn().mockResolvedValue(JSON.stringify(responsePayload)),
421
+ ok: true,
422
+ };
423
+ fetchMock.mockResolvedValue(mockResponse);
424
+ const result = await provider.callApi(PROMPT);
425
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
426
+ expect(result.output).toBe(responsePayload.result.response);
427
+ expect(result.tokenUsage).toEqual(tokenUsageDefaultResponse);
428
+ const resultFromCache = await provider.callApi(PROMPT);
429
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(2);
430
+ expect(resultFromCache.output).toBe(responsePayload.result.response);
431
+ expect(resultFromCache.tokenUsage).toEqual(tokenUsageDefaultResponse);
432
+ }
433
+ finally {
434
+ (0, cache_1.enableCache)();
435
+ }
436
+ });
437
+ it('callApi handles cloudflare error properly', async () => {
438
+ const PROMPT = 'Test prompt for caching';
439
+ const provider = new cloudflare_ai_1.CloudflareAiCompletionProvider(testModelName, {
440
+ config: cloudflareMinimumConfig,
441
+ });
442
+ const responsePayload = {
443
+ success: false,
444
+ errors: ['Some error occurred'],
445
+ messages: [],
446
+ };
447
+ const mockResponse = {
448
+ text: jest.fn().mockResolvedValue(JSON.stringify(responsePayload)),
449
+ ok: true,
450
+ };
451
+ fetchMock.mockResolvedValue(mockResponse);
452
+ const result = await provider.callApi(PROMPT);
453
+ expect(result.error).toContain(JSON.stringify(responsePayload.errors));
454
+ });
455
+ it('Can be invoked with custom configuration', async () => {
456
+ const cloudflareChatConfig = {
457
+ accountId: 'MADE_UP_ACCOUNT_ID',
458
+ apiKey: 'MADE_UP_API_KEY',
459
+ frequency_penalty: 10,
460
+ };
461
+ const rawProviderConfigs = [
462
+ {
463
+ [`cloudflare-ai:completion:${testModelName}`]: {
464
+ config: cloudflareChatConfig,
465
+ },
466
+ },
467
+ ];
468
+ const providers = await (0, providers_1.loadApiProviders)(rawProviderConfigs);
469
+ expect(providers).toHaveLength(1);
470
+ expect(providers[0]).toBeInstanceOf(cloudflare_ai_1.CloudflareAiCompletionProvider);
471
+ const cfProvider = providers[0];
472
+ expect(cfProvider.config).toEqual(cloudflareChatConfig);
473
+ const PROMPT = 'Test prompt for custom configuration';
474
+ const responsePayload = {
475
+ success: true,
476
+ errors: [],
477
+ messages: [],
478
+ result: {
479
+ response: 'Test text output',
480
+ },
481
+ };
482
+ const mockResponse = {
483
+ text: jest.fn().mockResolvedValue(JSON.stringify(responsePayload)),
484
+ ok: true,
485
+ };
486
+ fetchMock.mockResolvedValue(mockResponse);
487
+ await cfProvider.callApi(PROMPT);
488
+ expect(fetchMock).toHaveBeenCalledTimes(1);
489
+ expect(fetchMock.mock.calls).toHaveLength(1);
490
+ const [url, options] = fetchMock.mock.calls[0] ?? [undefined, {}];
491
+ const { body, headers, method } = options;
492
+ expect(url).toContain(cloudflareChatConfig.accountId);
493
+ expect(method).toBe('POST');
494
+ expect(headers && 'Authorization' in headers ? headers['Authorization'] : '').toContain(cloudflareChatConfig.apiKey);
495
+ const hydratedBody = typeof body === 'string' ? JSON.parse(body) : body;
496
+ expect(hydratedBody.prompt).toBe(PROMPT);
497
+ const { accountId, apiKey, ...passThroughConfig } = cloudflareChatConfig;
498
+ const { prompt, ...bodyWithoutPrompt } = hydratedBody;
499
+ expect(bodyWithoutPrompt).toEqual(passThroughConfig);
500
+ });
501
+ });
502
+ describe('CloudflareAiChatCompletionProvider', () => {
503
+ it('Should handle chat provider', async () => {
504
+ const provider = new cloudflare_ai_1.CloudflareAiChatCompletionProvider(testModelName, {
505
+ config: cloudflareMinimumConfig,
506
+ });
507
+ const responsePayload = {
508
+ success: true,
509
+ errors: [],
510
+ messages: [],
511
+ result: {
512
+ response: 'Test text output',
513
+ },
514
+ };
515
+ const mockResponse = {
516
+ text: jest.fn().mockResolvedValue(JSON.stringify(responsePayload)),
517
+ ok: true,
518
+ };
519
+ fetchMock.mockResolvedValue(mockResponse);
520
+ const result = await provider.callApi('Test chat prompt');
521
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
522
+ expect(result.output).toBe(responsePayload.result.response);
523
+ expect(result.tokenUsage).toEqual(tokenUsageDefaultResponse);
524
+ });
525
+ });
526
+ describe('CloudflareAiEmbeddingProvider', () => {
527
+ it('Should return embeddings in the proper format', async () => {
528
+ const provider = new cloudflare_ai_1.CloudflareAiEmbeddingProvider(testModelName, {
529
+ config: cloudflareMinimumConfig,
530
+ });
531
+ const responsePayload = {
532
+ success: true,
533
+ errors: [],
534
+ messages: [],
535
+ result: {
536
+ shape: [1, 3],
537
+ data: [[0.02055364102125168, -0.013749595731496811, 0.0024201320484280586]],
538
+ },
539
+ };
540
+ const mockResponse = {
541
+ text: jest.fn().mockResolvedValue(JSON.stringify(responsePayload)),
542
+ ok: true,
543
+ };
544
+ fetchMock.mockResolvedValue(mockResponse);
545
+ const result = await provider.callEmbeddingApi('Create embeddings from this');
546
+ expect(node_fetch_1.default).toHaveBeenCalledTimes(1);
547
+ expect(result.embedding).toEqual(responsePayload.result.data[0]);
548
+ expect(result.tokenUsage).toEqual(tokenUsageDefaultResponse);
549
+ });
550
+ });
551
+ });
552
+ describe.each([
553
+ ['python rag.py', 'python', ['rag.py']],
554
+ ['echo "hello world"', 'echo', ['hello world']],
555
+ ['./path/to/file.py run', './path/to/file.py', ['run']],
556
+ ['"/Path/To/My File.py"', '/Path/To/My File.py', []],
557
+ ])('ScriptCompletionProvider callApi with script %s', (script, inputFile, inputArgs) => {
558
+ it('returns expected output', async () => {
559
+ const mockResponse = 'Test script output';
560
+ const mockChildProcess = {
561
+ stdout: new stream_1.default.Readable(),
562
+ stderr: new stream_1.default.Readable(),
563
+ };
564
+ const execFileSpy = jest
565
+ .spyOn(child_process_1.default, 'execFile')
566
+ .mockImplementation((file, args, options, callback) => {
567
+ process.nextTick(() => callback && callback(null, Buffer.from(mockResponse), Buffer.from('')));
568
+ return mockChildProcess;
569
+ });
570
+ const provider = new scriptCompletion_1.ScriptCompletionProvider(script, {
571
+ config: {
572
+ some_config_val: 42,
573
+ },
574
+ });
575
+ const result = await provider.callApi('Test prompt', {
576
+ vars: {
577
+ var1: 'value 1',
578
+ var2: 'value 2 "with some double "quotes""',
579
+ },
580
+ });
581
+ expect(result.output).toBe(mockResponse);
582
+ expect(execFileSpy).toHaveBeenCalledTimes(1);
583
+ expect(execFileSpy).toHaveBeenCalledWith(expect.stringContaining(inputFile), expect.arrayContaining(inputArgs.concat([
584
+ 'Test prompt',
585
+ '{"config":{"some_config_val":42}}',
586
+ '{"vars":{"var1":"value 1","var2":"value 2 \\"with some double \\"quotes\\"\\""}}',
587
+ ])), expect.any(Object), expect.any(Function));
588
+ jest.restoreAllMocks();
589
+ });
590
+ });
591
+ });
592
+ describe('loadApiProvider', () => {
593
+ it('loadApiProvider with filepath', async () => {
594
+ const mockYamlContent = `id: 'openai:gpt-4'
595
+ config:
596
+ key: 'value'`;
597
+ jest.mocked(fs.readFileSync).mockReturnValueOnce(mockYamlContent);
598
+ const provider = await (0, providers_1.loadApiProvider)('file://path/to/mock-provider-file.yaml');
599
+ expect(provider.id()).toBe('openai:gpt-4');
600
+ expect(fs.readFileSync).toHaveBeenCalledTimes(1);
601
+ expect(fs.readFileSync).toHaveBeenCalledWith(expect.stringMatching(/path[\\\/]to[\\\/]mock-provider-file\.yaml/), 'utf8');
602
+ });
603
+ it('loadApiProvider with openai:chat', async () => {
604
+ const provider = await (0, providers_1.loadApiProvider)('openai:chat');
605
+ expect(provider).toBeInstanceOf(openai_1.OpenAiChatCompletionProvider);
606
+ });
607
+ it('loadApiProvider with openai:completion', async () => {
608
+ const provider = await (0, providers_1.loadApiProvider)('openai:completion');
609
+ expect(provider).toBeInstanceOf(openai_1.OpenAiCompletionProvider);
610
+ });
611
+ it('loadApiProvider with openai:assistant', async () => {
612
+ const provider = await (0, providers_1.loadApiProvider)('openai:assistant:foobar');
613
+ expect(provider).toBeInstanceOf(openai_1.OpenAiAssistantProvider);
614
+ });
615
+ it('loadApiProvider with openai:chat:modelName', async () => {
616
+ const provider = await (0, providers_1.loadApiProvider)('openai:chat:gpt-3.5-turbo');
617
+ expect(provider).toBeInstanceOf(openai_1.OpenAiChatCompletionProvider);
618
+ });
619
+ it('loadApiProvider with openai:completion:modelName', async () => {
620
+ const provider = await (0, providers_1.loadApiProvider)('openai:completion:text-davinci-003');
621
+ expect(provider).toBeInstanceOf(openai_1.OpenAiCompletionProvider);
622
+ });
623
+ it('loadApiProvider with OpenAI finetuned model', async () => {
624
+ const provider = await (0, providers_1.loadApiProvider)('openai:chat:ft:gpt-3.5-turbo-0613:company-name::ID:');
625
+ expect(provider).toBeInstanceOf(openai_1.OpenAiChatCompletionProvider);
626
+ expect(provider.id()).toBe('openai:ft:gpt-3.5-turbo-0613:company-name::ID:');
627
+ });
628
+ it('loadApiProvider with azureopenai:completion:modelName', async () => {
629
+ const provider = await (0, providers_1.loadApiProvider)('azureopenai:completion:text-davinci-003');
630
+ expect(provider).toBeInstanceOf(azureopenai_1.AzureOpenAiCompletionProvider);
631
+ });
632
+ it('loadApiProvider with azureopenai:chat:modelName', async () => {
633
+ const provider = await (0, providers_1.loadApiProvider)('azureopenai:chat:gpt-3.5-turbo');
634
+ expect(provider).toBeInstanceOf(azureopenai_1.AzureOpenAiChatCompletionProvider);
635
+ });
636
+ it('loadApiProvider with anthropic:completion', async () => {
637
+ const provider = await (0, providers_1.loadApiProvider)('anthropic:completion');
638
+ expect(provider).toBeInstanceOf(anthropic_1.AnthropicCompletionProvider);
639
+ });
640
+ it('loadApiProvider with anthropic:completion:modelName', async () => {
641
+ const provider = await (0, providers_1.loadApiProvider)('anthropic:completion:claude-1');
642
+ expect(provider).toBeInstanceOf(anthropic_1.AnthropicCompletionProvider);
643
+ });
644
+ it('loadApiProvider with ollama:modelName', async () => {
645
+ const provider = await (0, providers_1.loadApiProvider)('ollama:llama2:13b');
646
+ expect(provider).toBeInstanceOf(ollama_1.OllamaCompletionProvider);
647
+ expect(provider.id()).toBe('ollama:completion:llama2:13b');
648
+ });
649
+ it('loadApiProvider with ollama:completion:modelName', async () => {
650
+ const provider = await (0, providers_1.loadApiProvider)('ollama:completion:llama2:13b');
651
+ expect(provider).toBeInstanceOf(ollama_1.OllamaCompletionProvider);
652
+ expect(provider.id()).toBe('ollama:completion:llama2:13b');
653
+ });
654
+ it('loadApiProvider with ollama:embedding:modelName', async () => {
655
+ const provider = await (0, providers_1.loadApiProvider)('ollama:embedding:llama2:13b');
656
+ expect(provider).toBeInstanceOf(ollama_1.OllamaEmbeddingProvider);
657
+ });
658
+ it('loadApiProvider with ollama:embeddings:modelName', async () => {
659
+ const provider = await (0, providers_1.loadApiProvider)('ollama:embeddings:llama2:13b');
660
+ expect(provider).toBeInstanceOf(ollama_1.OllamaEmbeddingProvider);
661
+ });
662
+ it('loadApiProvider with ollama:chat:modelName', async () => {
663
+ const provider = await (0, providers_1.loadApiProvider)('ollama:chat:llama2:13b');
664
+ expect(provider).toBeInstanceOf(ollama_1.OllamaChatProvider);
665
+ expect(provider.id()).toBe('ollama:chat:llama2:13b');
666
+ });
667
+ it('loadApiProvider with llama:modelName', async () => {
668
+ const provider = await (0, providers_1.loadApiProvider)('llama');
669
+ expect(provider).toBeInstanceOf(llama_1.LlamaProvider);
670
+ });
671
+ it('loadApiProvider with webhook', async () => {
672
+ const provider = await (0, providers_1.loadApiProvider)('webhook:http://example.com/webhook');
673
+ expect(provider).toBeInstanceOf(webhook_1.WebhookProvider);
674
+ });
675
+ it('loadApiProvider with huggingface:text-generation', async () => {
676
+ const provider = await (0, providers_1.loadApiProvider)('huggingface:text-generation:foobar/baz');
677
+ expect(provider).toBeInstanceOf(huggingface_1.HuggingfaceTextGenerationProvider);
678
+ });
679
+ it('loadApiProvider with huggingface:feature-extraction', async () => {
680
+ const provider = await (0, providers_1.loadApiProvider)('huggingface:feature-extraction:foobar/baz');
681
+ expect(provider).toBeInstanceOf(huggingface_1.HuggingfaceFeatureExtractionProvider);
682
+ });
683
+ it('loadApiProvider with huggingface:text-classification', async () => {
684
+ const provider = await (0, providers_1.loadApiProvider)('huggingface:text-classification:foobar/baz');
685
+ expect(provider).toBeInstanceOf(huggingface_1.HuggingfaceTextClassificationProvider);
686
+ });
687
+ it('loadApiProvider with hf:text-classification', async () => {
688
+ const provider = await (0, providers_1.loadApiProvider)('hf:text-classification:foobar/baz');
689
+ expect(provider).toBeInstanceOf(huggingface_1.HuggingfaceTextClassificationProvider);
690
+ });
691
+ it('loadApiProvider with bedrock:completion', async () => {
692
+ const provider = await (0, providers_1.loadApiProvider)('bedrock:completion:anthropic.claude-v2:1');
693
+ expect(provider).toBeInstanceOf(bedrock_1.AwsBedrockCompletionProvider);
694
+ });
695
+ it('loadApiProvider with openrouter', async () => {
696
+ const provider = await (0, providers_1.loadApiProvider)('openrouter:mistralai/mistral-medium');
697
+ expect(provider).toBeInstanceOf(openai_1.OpenAiChatCompletionProvider);
698
+ // Intentionally openai, because it's just a wrapper around openai
699
+ expect(provider.id()).toBe('mistralai/mistral-medium');
700
+ });
701
+ it('loadApiProvider with voyage', async () => {
702
+ const provider = await (0, providers_1.loadApiProvider)('voyage:voyage-2');
703
+ expect(provider).toBeInstanceOf(voyage_1.VoyageEmbeddingProvider);
704
+ expect(provider.id()).toBe('voyage:voyage-2');
705
+ });
706
+ it('loadApiProvider with vertex:chat', async () => {
707
+ const provider = await (0, providers_1.loadApiProvider)('vertex:chat:vertex-chat-model');
708
+ expect(provider).toBeInstanceOf(vertex_1.VertexChatProvider);
709
+ expect(provider.id()).toBe('vertex:vertex-chat-model');
710
+ });
711
+ it('loadApiProvider with vertex:embedding', async () => {
712
+ const provider = await (0, providers_1.loadApiProvider)('vertex:embedding:vertex-embedding-model');
713
+ expect(provider).toBeInstanceOf(vertex_1.VertexEmbeddingProvider);
714
+ expect(provider.id()).toBe('vertex:vertex-embedding-model');
715
+ });
716
+ it('loadApiProvider with vertex:embeddings', async () => {
717
+ const provider = await (0, providers_1.loadApiProvider)('vertex:embeddings:vertex-embedding-model');
718
+ expect(provider).toBeInstanceOf(vertex_1.VertexEmbeddingProvider);
719
+ expect(provider.id()).toBe('vertex:vertex-embedding-model');
720
+ });
721
+ it('loadApiProvider with vertex:modelname', async () => {
722
+ const provider = await (0, providers_1.loadApiProvider)('vertex:vertex-chat-model');
723
+ expect(provider).toBeInstanceOf(vertex_1.VertexChatProvider);
724
+ expect(provider.id()).toBe('vertex:vertex-chat-model');
725
+ });
726
+ it('loadApiProvider with replicate:modelname', async () => {
727
+ const provider = await (0, providers_1.loadApiProvider)('replicate:meta/llama3');
728
+ expect(provider).toBeInstanceOf(replicate_1.ReplicateProvider);
729
+ expect(provider.id()).toBe('replicate:meta/llama3');
730
+ });
731
+ it('loadApiProvider with replicate:modelname:version', async () => {
732
+ const provider = await (0, providers_1.loadApiProvider)('replicate:meta/llama3:abc123');
733
+ expect(provider).toBeInstanceOf(replicate_1.ReplicateProvider);
734
+ expect(provider.id()).toBe('replicate:meta/llama3:abc123');
735
+ });
736
+ it('loadApiProvider with replicate:image', async () => {
737
+ const provider = await (0, providers_1.loadApiProvider)('replicate:image:stability-ai/sdxl');
738
+ expect(provider).toBeInstanceOf(replicate_1.ReplicateImageProvider);
739
+ expect(provider.id()).toBe('replicate:stability-ai/sdxl');
740
+ });
741
+ it('loadApiProvider with replicate:image:version', async () => {
742
+ const provider = await (0, providers_1.loadApiProvider)('replicate:image:stability-ai/sdxl:abc123');
743
+ expect(provider).toBeInstanceOf(replicate_1.ReplicateImageProvider);
744
+ expect(provider.id()).toBe('replicate:stability-ai/sdxl:abc123');
745
+ });
746
+ it('loadApiProvider with replicate:moderation', async () => {
747
+ const provider = await (0, providers_1.loadApiProvider)('replicate:moderation:foo/bar');
748
+ expect(provider).toBeInstanceOf(replicate_1.ReplicateModerationProvider);
749
+ expect(provider.id()).toBe('replicate:foo/bar');
750
+ });
751
+ it('loadApiProvider with replicate:moderation:version', async () => {
752
+ const provider = await (0, providers_1.loadApiProvider)('replicate:moderation:foo/bar:abc123');
753
+ expect(provider).toBeInstanceOf(replicate_1.ReplicateModerationProvider);
754
+ expect(provider.id()).toBe('replicate:foo/bar:abc123');
755
+ });
756
+ it('loadApiProvider with cloudflare-ai', async () => {
757
+ const supportedModelTypes = [
758
+ { modelType: 'chat', providerKlass: cloudflare_ai_1.CloudflareAiChatCompletionProvider },
759
+ { modelType: 'embedding', providerKlass: cloudflare_ai_1.CloudflareAiEmbeddingProvider },
760
+ { modelType: 'embeddings', providerKlass: cloudflare_ai_1.CloudflareAiEmbeddingProvider },
761
+ { modelType: 'completion', providerKlass: cloudflare_ai_1.CloudflareAiCompletionProvider },
762
+ ];
763
+ const unsupportedModelTypes = ['assistant'];
764
+ const modelName = 'mistralai/mistral-medium';
765
+ // Without any model type should throw an error
766
+ await expect((0, providers_1.loadApiProvider)(`cloudflare-ai:${modelName}`)).rejects.toThrow(/Unknown Cloudflare AI model type/);
767
+ for (const unsupportedModelType of unsupportedModelTypes) {
768
+ await expect((0, providers_1.loadApiProvider)(`cloudflare-ai:${unsupportedModelType}:${modelName}`)).rejects.toThrow(/Unknown Cloudflare AI model type/);
769
+ }
770
+ for (const { modelType, providerKlass } of supportedModelTypes) {
771
+ const cfProvider = await (0, providers_1.loadApiProvider)(`cloudflare-ai:${modelType}:${modelName}`);
772
+ const modelTypeForId = modelType === 'embeddings' ? 'embedding' : modelType;
773
+ expect(cfProvider.id()).toMatch(`cloudflare-ai:${modelTypeForId}:${modelName}`);
774
+ expect(cfProvider).toBeInstanceOf(providerKlass);
775
+ }
776
+ });
777
+ it('loadApiProvider with promptfoo:redteam:iterative', async () => {
778
+ const provider = await (0, providers_1.loadApiProvider)('promptfoo:redteam:iterative');
779
+ expect(provider).toBeInstanceOf(iterative_1.default);
780
+ expect(provider.id()).toBe('promptfoo:redteam:iterative');
781
+ });
782
+ it('loadApiProvider with promptfoo:redteam:iterative:image', async () => {
783
+ const provider = await (0, providers_1.loadApiProvider)('promptfoo:redteam:iterative:image');
784
+ expect(provider).toBeInstanceOf(iterativeImage_1.default);
785
+ expect(provider.id()).toBe('promptfoo:redteam:iterative:image');
786
+ });
787
+ it('loadApiProvider with RawProviderConfig', async () => {
788
+ const rawProviderConfig = {
789
+ 'openai:chat': {
790
+ id: 'test',
791
+ config: { foo: 'bar' },
792
+ },
793
+ };
794
+ const provider = await (0, providers_1.loadApiProvider)('openai:chat', {
795
+ options: rawProviderConfig['openai:chat'],
796
+ });
797
+ expect(provider).toBeInstanceOf(openai_1.OpenAiChatCompletionProvider);
798
+ });
799
+ it('loadApiProviders with ProviderFunction', async () => {
800
+ const providerFunction = async (prompt) => {
801
+ return {
802
+ output: `Output for ${prompt}`,
803
+ tokenUsage: { total: 10, prompt: 5, completion: 5 },
804
+ };
805
+ };
806
+ const providers = await (0, providers_1.loadApiProviders)(providerFunction);
807
+ expect(providers).toHaveLength(1);
808
+ expect(providers[0].id()).toBe('custom-function');
809
+ const response = await providers[0].callApi('Test prompt');
810
+ expect(response.output).toBe('Output for Test prompt');
811
+ expect(response.tokenUsage).toEqual({ total: 10, prompt: 5, completion: 5 });
812
+ });
813
+ it('loadApiProviders with CustomApiProvider', async () => {
814
+ const providerPath = 'file://path/to/file.js';
815
+ class CustomApiProvider {
816
+ id() {
817
+ return 'custom-api-provider';
818
+ }
819
+ async callApi(input) {
820
+ return { output: `Processed ${input}` };
821
+ }
822
+ }
823
+ jest.mocked(esm_1.importModule).mockResolvedValue(CustomApiProvider);
824
+ const providers = await (0, providers_1.loadApiProviders)(providerPath);
825
+ expect(esm_1.importModule).toHaveBeenCalledWith(path.resolve('path/to/file.js'));
826
+ expect(providers).toHaveLength(1);
827
+ expect(providers[0].id()).toBe('custom-api-provider');
828
+ const response = await providers[0].callApi('Test input');
829
+ expect(response.output).toBe('Processed Test input');
830
+ });
831
+ it('loadApiProviders with CustomApiProvider, absolute path', async () => {
832
+ const providerPath = 'file:///absolute/path/to/file.js';
833
+ class CustomApiProvider {
834
+ id() {
835
+ return 'custom-api-provider';
836
+ }
837
+ async callApi(input) {
838
+ return { output: `Processed ${input}` };
839
+ }
840
+ }
841
+ jest.mocked(esm_1.importModule).mockResolvedValue(CustomApiProvider);
842
+ const providers = await (0, providers_1.loadApiProviders)(providerPath);
843
+ expect(esm_1.importModule).toHaveBeenCalledWith('/absolute/path/to/file.js');
844
+ expect(providers).toHaveLength(1);
845
+ expect(providers[0].id()).toBe('custom-api-provider');
846
+ const response = await providers[0].callApi('Test input');
847
+ expect(response.output).toBe('Processed Test input');
848
+ });
849
+ it('loadApiProviders with RawProviderConfig[]', async () => {
850
+ const rawProviderConfigs = [
851
+ {
852
+ 'openai:chat:abc123': {
853
+ config: { foo: 'bar' },
854
+ },
855
+ },
856
+ {
857
+ 'openai:completion:def456': {
858
+ config: { foo: 'bar' },
859
+ },
860
+ },
861
+ {
862
+ 'anthropic:completion:ghi789': {
863
+ config: { foo: 'bar' },
864
+ },
865
+ },
866
+ ];
867
+ const providers = await (0, providers_1.loadApiProviders)(rawProviderConfigs);
868
+ expect(providers).toHaveLength(3);
869
+ expect(providers[0]).toBeInstanceOf(openai_1.OpenAiChatCompletionProvider);
870
+ expect(providers[1]).toBeInstanceOf(openai_1.OpenAiCompletionProvider);
871
+ expect(providers[2]).toBeInstanceOf(anthropic_1.AnthropicCompletionProvider);
872
+ });
873
+ it('loadApiProvider sets provider.delay', async () => {
874
+ const providerOptions = {
875
+ id: 'test-delay',
876
+ config: {},
877
+ delay: 500,
878
+ };
879
+ const provider = await (0, providers_1.loadApiProvider)('echo', { options: providerOptions });
880
+ expect(provider.delay).toBe(500);
881
+ });
882
+ });
883
+ //# sourceMappingURL=providers.test.js.map