@use-lattice/litmus 0.121.3

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 (199) hide show
  1. package/LICENSE +19 -0
  2. package/dist/src/accounts-Bt1oJb1Z.cjs +219 -0
  3. package/dist/src/accounts-DjOU8Rm3.js +178 -0
  4. package/dist/src/agentic-utils-D03IiXQc.js +153 -0
  5. package/dist/src/agentic-utils-Dh7xaMQM.cjs +180 -0
  6. package/dist/src/agents-C6BIMlZa.js +231 -0
  7. package/dist/src/agents-DvIpNX1L.cjs +666 -0
  8. package/dist/src/agents-ZP0RP9vV.cjs +231 -0
  9. package/dist/src/agents-maJXdjbR.js +665 -0
  10. package/dist/src/aimlapi-BTbQjG2E.cjs +30 -0
  11. package/dist/src/aimlapi-CwMxqfXP.js +30 -0
  12. package/dist/src/audio-BBUdvsde.cjs +97 -0
  13. package/dist/src/audio-D5DPZ7I-.js +97 -0
  14. package/dist/src/base-BEysXrkq.cjs +222 -0
  15. package/dist/src/base-C451JQfq.js +193 -0
  16. package/dist/src/blobs-BY8MDmpo.js +230 -0
  17. package/dist/src/blobs-BgcNn97m.cjs +256 -0
  18. package/dist/src/cache-BBE_lsTA.cjs +4 -0
  19. package/dist/src/cache-BkrqU5Ba.js +237 -0
  20. package/dist/src/cache-DsCxFlsZ.cjs +297 -0
  21. package/dist/src/chat-CPJWDP6a.cjs +289 -0
  22. package/dist/src/chat-CXX3xzkk.cjs +811 -0
  23. package/dist/src/chat-CcDgZFJ4.js +787 -0
  24. package/dist/src/chat-Dz5ZeGO2.js +289 -0
  25. package/dist/src/chatkit-Dw0mKkML.cjs +1158 -0
  26. package/dist/src/chatkit-swAIVuea.js +1157 -0
  27. package/dist/src/chunk-DEq-mXcV.js +15 -0
  28. package/dist/src/claude-agent-sdk-BXZJtOg6.js +379 -0
  29. package/dist/src/claude-agent-sdk-CkfyjDoG.cjs +383 -0
  30. package/dist/src/cloudflare-ai-BzpJcqUH.js +161 -0
  31. package/dist/src/cloudflare-ai-Cmy_R1y2.cjs +161 -0
  32. package/dist/src/cloudflare-gateway-B9tVQKok.cjs +272 -0
  33. package/dist/src/cloudflare-gateway-DrD3ew3H.js +272 -0
  34. package/dist/src/codex-sdk-Dezj9Nwm.js +1056 -0
  35. package/dist/src/codex-sdk-Dl9D4k5B.cjs +1060 -0
  36. package/dist/src/cometapi-C-9YvCHC.js +54 -0
  37. package/dist/src/cometapi-DHgDKoO2.cjs +54 -0
  38. package/dist/src/completion-B8Ctyxpr.js +120 -0
  39. package/dist/src/completion-Cxrt08sj.cjs +131 -0
  40. package/dist/src/createHash-BwgE13yv.cjs +27 -0
  41. package/dist/src/createHash-DmPQkvBh.js +15 -0
  42. package/dist/src/docker-BiqcTwLv.js +80 -0
  43. package/dist/src/docker-C7tEJnP-.cjs +80 -0
  44. package/dist/src/esm-C62Zofr1.cjs +409 -0
  45. package/dist/src/esm-DMVc93eh.js +379 -0
  46. package/dist/src/evalResult-C3NJPQOo.cjs +301 -0
  47. package/dist/src/evalResult-C7JJAPBb.js +295 -0
  48. package/dist/src/evalResult-DoVTZZWI.cjs +2 -0
  49. package/dist/src/extractor-DnMD3fwt.cjs +391 -0
  50. package/dist/src/extractor-DtlL28vL.js +374 -0
  51. package/dist/src/fetch-BTxakTSg.cjs +1133 -0
  52. package/dist/src/fetch-DQckpUFz.js +928 -0
  53. package/dist/src/fileExtensions-DnqA1y9x.js +85 -0
  54. package/dist/src/fileExtensions-bYh77CN8.cjs +114 -0
  55. package/dist/src/genaiTracer-CyZrmaK0.cjs +268 -0
  56. package/dist/src/genaiTracer-D3fD9dNV.js +256 -0
  57. package/dist/src/graders-BNscxFrU.js +13644 -0
  58. package/dist/src/graders-D2oE9Msq.js +2 -0
  59. package/dist/src/graders-c0Ez_w-9.cjs +2 -0
  60. package/dist/src/graders-d0F2M3e9.cjs +14056 -0
  61. package/dist/src/image-0ZhE0VlR.cjs +280 -0
  62. package/dist/src/image-CWE1pdNv.js +257 -0
  63. package/dist/src/image-D9ZK6hwL.js +163 -0
  64. package/dist/src/image-DKZgZITg.cjs +163 -0
  65. package/dist/src/index.cjs +11366 -0
  66. package/dist/src/index.d.cts +19640 -0
  67. package/dist/src/index.d.ts +19641 -0
  68. package/dist/src/index.js +11306 -0
  69. package/dist/src/invariant-Ddh24eXh.js +25 -0
  70. package/dist/src/invariant-kfQ8Bu82.cjs +30 -0
  71. package/dist/src/knowledgeBase-BgPyGFUd.cjs +122 -0
  72. package/dist/src/knowledgeBase-DyHilYaP.js +122 -0
  73. package/dist/src/litellm-CyMeneHS.js +135 -0
  74. package/dist/src/litellm-DWDF73yF.cjs +135 -0
  75. package/dist/src/logger-C40ZGil9.js +717 -0
  76. package/dist/src/logger-DyfK9PBt.cjs +917 -0
  77. package/dist/src/luma-ray-BAU9X_ep.cjs +315 -0
  78. package/dist/src/luma-ray-nwVseBbv.js +313 -0
  79. package/dist/src/messages-B5ADWTTv.js +245 -0
  80. package/dist/src/messages-BCnZfqrS.cjs +257 -0
  81. package/dist/src/meteor-DLZZ3osF.cjs +134 -0
  82. package/dist/src/meteor-DUiCJRC-.js +134 -0
  83. package/dist/src/modelslab-00cveB8L.cjs +163 -0
  84. package/dist/src/modelslab-D9sCU_L7.js +163 -0
  85. package/dist/src/nova-reel-CTapvqYH.js +276 -0
  86. package/dist/src/nova-reel-DlWuuroF.cjs +278 -0
  87. package/dist/src/nova-sonic-5UPWfeMv.cjs +363 -0
  88. package/dist/src/nova-sonic-BhSwQNym.js +363 -0
  89. package/dist/src/openai-BWrJK9d8.cjs +52 -0
  90. package/dist/src/openai-DumO8WQn.js +47 -0
  91. package/dist/src/openclaw-B8brrjC_.cjs +577 -0
  92. package/dist/src/openclaw-Bkayww9q.js +571 -0
  93. package/dist/src/opencode-sdk-7xjoDNiM.cjs +562 -0
  94. package/dist/src/opencode-sdk-SGwAPxht.js +558 -0
  95. package/dist/src/otlpReceiver-CoAHfAN9.cjs +15 -0
  96. package/dist/src/otlpReceiver-oO3EQwI9.js +14 -0
  97. package/dist/src/providerRegistry-4yjhaEM8.js +45 -0
  98. package/dist/src/providerRegistry-DhV4rJIc.cjs +50 -0
  99. package/dist/src/providers-B5RJVG-7.cjs +33609 -0
  100. package/dist/src/providers-BdmZCLzV.js +33262 -0
  101. package/dist/src/providers-CxtRxn8e.js +2 -0
  102. package/dist/src/providers-DnQLNbx1.cjs +3 -0
  103. package/dist/src/pythonUtils-BD0druiM.cjs +275 -0
  104. package/dist/src/pythonUtils-IBhn5YGR.js +249 -0
  105. package/dist/src/quiverai-BDOwZBsM.cjs +213 -0
  106. package/dist/src/quiverai-D3JTF5lD.js +213 -0
  107. package/dist/src/responses-B2LCDCXZ.js +667 -0
  108. package/dist/src/responses-BvNm4Xv9.cjs +685 -0
  109. package/dist/src/rubyUtils-B0NwnfpY.cjs +245 -0
  110. package/dist/src/rubyUtils-BroxzZ7c.cjs +2 -0
  111. package/dist/src/rubyUtils-hqVw5UvJ.js +222 -0
  112. package/dist/src/sagemaker-Cno2V-Sx.js +689 -0
  113. package/dist/src/sagemaker-fV_KUgs5.cjs +691 -0
  114. package/dist/src/server-BOuAXb06.cjs +238 -0
  115. package/dist/src/server-CtI-EWzm.cjs +2 -0
  116. package/dist/src/server-Cy3DZymt.js +189 -0
  117. package/dist/src/slack-CP8xBePa.js +135 -0
  118. package/dist/src/slack-DSQ1yXVb.cjs +135 -0
  119. package/dist/src/store-BwDDaBjb.cjs +246 -0
  120. package/dist/src/store-DcbLC593.cjs +2 -0
  121. package/dist/src/store-IGpqMIkv.js +240 -0
  122. package/dist/src/tables-3Q2cL7So.cjs +373 -0
  123. package/dist/src/tables-Bi2fjr4W.js +288 -0
  124. package/dist/src/telemetry-Bg2WqF79.js +161 -0
  125. package/dist/src/telemetry-D0x6u5kX.cjs +166 -0
  126. package/dist/src/telemetry-DXNimrI0.cjs +2 -0
  127. package/dist/src/text-B_UCRPp2.js +22 -0
  128. package/dist/src/text-CW1cyrwj.cjs +33 -0
  129. package/dist/src/tokenUsageUtils-NYT-WKS6.js +138 -0
  130. package/dist/src/tokenUsageUtils-bVa1ga6f.cjs +173 -0
  131. package/dist/src/transcription-Cl_W16Pr.js +122 -0
  132. package/dist/src/transcription-yt1EecY8.cjs +124 -0
  133. package/dist/src/transform-BCtGrl_W.cjs +228 -0
  134. package/dist/src/transform-Bv6gG2MJ.cjs +1688 -0
  135. package/dist/src/transform-CY1wbpRy.js +1507 -0
  136. package/dist/src/transform-DU8rUL9P.cjs +2 -0
  137. package/dist/src/transform-yWaShiKr.js +216 -0
  138. package/dist/src/transformersAvailability-BGkzavwb.js +35 -0
  139. package/dist/src/transformersAvailability-DKoRtQLy.cjs +35 -0
  140. package/dist/src/types-5aqHpBwE.cjs +3769 -0
  141. package/dist/src/types-Bn6D9c4U.js +3300 -0
  142. package/dist/src/util-BkKlTkI2.js +293 -0
  143. package/dist/src/util-CTh0bfOm.cjs +1119 -0
  144. package/dist/src/util-D17oBwo7.cjs +328 -0
  145. package/dist/src/util-DsS_-v4p.js +613 -0
  146. package/dist/src/util-DuntT1Ga.js +951 -0
  147. package/dist/src/util-aWjdCYMI.cjs +667 -0
  148. package/dist/src/utils-CisQwpjA.js +94 -0
  149. package/dist/src/utils-yWamDvmz.cjs +123 -0
  150. package/dist/tsconfig.tsbuildinfo +1 -0
  151. package/drizzle/0000_lush_hellion.sql +36 -0
  152. package/drizzle/0001_wide_calypso.sql +3 -0
  153. package/drizzle/0002_tidy_juggernaut.sql +1 -0
  154. package/drizzle/0003_lively_naoko.sql +8 -0
  155. package/drizzle/0004_minor_peter_quill.sql +19 -0
  156. package/drizzle/0005_silky_millenium_guard.sql +2 -0
  157. package/drizzle/0006_harsh_caretaker.sql +42 -0
  158. package/drizzle/0007_cloudy_wong.sql +1 -0
  159. package/drizzle/0008_broad_boomer.sql +2 -0
  160. package/drizzle/0009_strong_marten_broadcloak.sql +19 -0
  161. package/drizzle/0010_needy_bishop.sql +11 -0
  162. package/drizzle/0011_moaning_millenium_guard.sql +1 -0
  163. package/drizzle/0012_late_marten_broadcloak.sql +2 -0
  164. package/drizzle/0013_previous_dormammu.sql +9 -0
  165. package/drizzle/0014_lazy_captain_universe.sql +2 -0
  166. package/drizzle/0015_zippy_wallop.sql +29 -0
  167. package/drizzle/0016_jazzy_zemo.sql +2 -0
  168. package/drizzle/0017_reflective_praxagora.sql +4 -0
  169. package/drizzle/0018_fat_vanisher.sql +22 -0
  170. package/drizzle/0019_new_clint_barton.sql +8 -0
  171. package/drizzle/0020_skinny_maverick.sql +1 -0
  172. package/drizzle/0021_mysterious_madelyne_pryor.sql +13 -0
  173. package/drizzle/0022_sleepy_ultimo.sql +25 -0
  174. package/drizzle/0023_wooden_mandrill.sql +2 -0
  175. package/drizzle/AGENTS.md +68 -0
  176. package/drizzle/CLAUDE.md +1 -0
  177. package/drizzle/meta/0000_snapshot.json +221 -0
  178. package/drizzle/meta/0001_snapshot.json +214 -0
  179. package/drizzle/meta/0002_snapshot.json +221 -0
  180. package/drizzle/meta/0005_snapshot.json +369 -0
  181. package/drizzle/meta/0006_snapshot.json +638 -0
  182. package/drizzle/meta/0007_snapshot.json +640 -0
  183. package/drizzle/meta/0008_snapshot.json +649 -0
  184. package/drizzle/meta/0009_snapshot.json +554 -0
  185. package/drizzle/meta/0010_snapshot.json +619 -0
  186. package/drizzle/meta/0011_snapshot.json +627 -0
  187. package/drizzle/meta/0012_snapshot.json +639 -0
  188. package/drizzle/meta/0013_snapshot.json +717 -0
  189. package/drizzle/meta/0014_snapshot.json +717 -0
  190. package/drizzle/meta/0015_snapshot.json +897 -0
  191. package/drizzle/meta/0016_snapshot.json +1031 -0
  192. package/drizzle/meta/0018_snapshot.json +1210 -0
  193. package/drizzle/meta/0019_snapshot.json +1165 -0
  194. package/drizzle/meta/0020_snapshot.json +1232 -0
  195. package/drizzle/meta/0021_snapshot.json +1311 -0
  196. package/drizzle/meta/0022_snapshot.json +1481 -0
  197. package/drizzle/meta/0023_snapshot.json +1496 -0
  198. package/drizzle/meta/_journal.json +174 -0
  199. package/package.json +240 -0
package/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) Promptfoo 2025
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,219 @@
1
+ const require_logger = require("./logger-DyfK9PBt.cjs");
2
+ const require_fetch = require("./fetch-BTxakTSg.cjs");
3
+ const BAD_EMAIL_RESULT = "bad_email";
4
+ const EmailValidationStatus = {
5
+ OK: "ok",
6
+ EXCEEDED_LIMIT: "exceeded_limit",
7
+ SHOW_USAGE_WARNING: "show_usage_warning",
8
+ EMAIL_VERIFICATION_REQUIRED: "email_verification_required",
9
+ RISKY_EMAIL: "risky_email",
10
+ DISPOSABLE_EMAIL: "disposable_email"
11
+ };
12
+ const NO_EMAIL_STATUS = "no_email";
13
+ //#endregion
14
+ //#region src/globalConfig/accounts.ts
15
+ const CI_PLACEHOLDER_EMAIL = "ci-placeholder@promptfoo.dev";
16
+ function getUserId() {
17
+ let globalConfig = require_fetch.readGlobalConfig();
18
+ if (!globalConfig?.id) {
19
+ const newId = crypto.randomUUID();
20
+ globalConfig = {
21
+ ...globalConfig,
22
+ id: newId
23
+ };
24
+ require_fetch.writeGlobalConfig(globalConfig);
25
+ return newId;
26
+ }
27
+ return globalConfig.id;
28
+ }
29
+ function getUserEmail() {
30
+ return require_fetch.readGlobalConfig()?.account?.email || null;
31
+ }
32
+ function setUserEmail(email) {
33
+ const account = require_fetch.readGlobalConfig()?.account ?? {};
34
+ account.email = email;
35
+ require_fetch.writeGlobalConfigPartial({ account });
36
+ }
37
+ function getUserEmailNeedsValidation() {
38
+ return require_fetch.readGlobalConfig()?.account?.emailNeedsValidation || false;
39
+ }
40
+ function setUserEmailNeedsValidation(needsValidation) {
41
+ const account = require_fetch.readGlobalConfig()?.account ?? {};
42
+ account.emailNeedsValidation = needsValidation;
43
+ require_fetch.writeGlobalConfigPartial({ account });
44
+ }
45
+ function getUserEmailValidated() {
46
+ return require_fetch.readGlobalConfig()?.account?.emailValidated || false;
47
+ }
48
+ function setUserEmailValidated(validated) {
49
+ const account = require_fetch.readGlobalConfig()?.account ?? {};
50
+ account.emailValidated = validated;
51
+ require_fetch.writeGlobalConfigPartial({ account });
52
+ }
53
+ function getAuthor() {
54
+ return require_logger.getEnvString("PROMPTFOO_AUTHOR") || getUserEmail() || null;
55
+ }
56
+ function isLoggedIntoCloud() {
57
+ return new require_fetch.CloudConfig().isEnabled();
58
+ }
59
+ /**
60
+ * Get the authentication method used for cloud access
61
+ * @returns 'api-key' | 'email' | 'none'
62
+ */
63
+ function getAuthMethod() {
64
+ const hasApiKey = new require_fetch.CloudConfig().isEnabled();
65
+ const hasEmail = !!getUserEmail();
66
+ if (hasApiKey && hasEmail) return "api-key";
67
+ if (hasApiKey) return "api-key";
68
+ if (hasEmail) return "email";
69
+ return "none";
70
+ }
71
+ /**
72
+ * Shared function to check email status with the promptfoo API
73
+ * Used by both CLI and server routes
74
+ */
75
+ async function checkEmailStatus(options) {
76
+ const { default: telemetry } = await Promise.resolve().then(() => require("./telemetry-DXNimrI0.cjs"));
77
+ const ciMode = require_logger.isCI();
78
+ const userEmail = ciMode ? CI_PLACEHOLDER_EMAIL : getUserEmail();
79
+ if (!userEmail) return {
80
+ status: NO_EMAIL_STATUS,
81
+ hasEmail: false,
82
+ message: "Redteam evals require email verification. Please enter your work email:"
83
+ };
84
+ if (ciMode) return {
85
+ status: EmailValidationStatus.OK,
86
+ hasEmail: true,
87
+ email: userEmail
88
+ };
89
+ try {
90
+ const validateParam = options?.validate ? "&validate=true" : "";
91
+ const timeout = options?.validate ? 3e3 : 500;
92
+ if (options?.validate) require_logger.logger.info(`Checking email...`);
93
+ const data = await (await require_fetch.fetchWithTimeout(`${require_logger.getEnvString("PROMPTFOO_CLOUD_API_URL", "https://api.promptfoo.app")}/api/users/status?email=${encodeURIComponent(userEmail)}${validateParam}`, void 0, timeout)).json();
94
+ if (options?.validate) if (new Set([
95
+ EmailValidationStatus.RISKY_EMAIL,
96
+ EmailValidationStatus.DISPOSABLE_EMAIL,
97
+ EmailValidationStatus.EMAIL_VERIFICATION_REQUIRED
98
+ ]).has(data.status)) {
99
+ if (data.status === EmailValidationStatus.EMAIL_VERIFICATION_REQUIRED) {
100
+ setUserEmailValidated(false);
101
+ setUserEmailNeedsValidation(true);
102
+ }
103
+ if (data.status === EmailValidationStatus.RISKY_EMAIL || data.status === EmailValidationStatus.DISPOSABLE_EMAIL) await telemetry.saveConsent(userEmail, { source: "filteredInvalidEmail" });
104
+ } else {
105
+ setUserEmailValidated(true);
106
+ await telemetry.saveConsent(userEmail, { source: "promptForEmailValidated" });
107
+ }
108
+ return {
109
+ status: data.status,
110
+ message: data.message ?? data.error,
111
+ email: userEmail,
112
+ hasEmail: true
113
+ };
114
+ } catch (e) {
115
+ require_logger.logger.debug(`Failed to check user status: ${e}`);
116
+ return {
117
+ status: EmailValidationStatus.OK,
118
+ message: "Unable to verify email status, but proceeding",
119
+ email: userEmail,
120
+ hasEmail: true
121
+ };
122
+ }
123
+ }
124
+ async function promptForEmailUnverified() {
125
+ const { default: telemetry } = await Promise.resolve().then(() => require("./telemetry-DXNimrI0.cjs"));
126
+ const ciMode = require_logger.isCI();
127
+ const existingEmail = getUserEmail();
128
+ let email = ciMode ? CI_PLACEHOLDER_EMAIL : existingEmail;
129
+ const existingEmailNeedsValidation = !ciMode && getUserEmailNeedsValidation();
130
+ const existingEmailValidated = ciMode || getUserEmailValidated();
131
+ let emailNeedsValidation = existingEmailNeedsValidation && !existingEmailValidated;
132
+ if (!email) {
133
+ await telemetry.record("feature_used", { feature: "promptForEmailUnverified" });
134
+ const envEmail = require_logger.getEnvString("PROMPTFOO_EMAIL");
135
+ if (!envEmail) throw new Error("Email verification required for red team scans. Set the PROMPTFOO_EMAIL environment variable to your work email address.");
136
+ email = envEmail;
137
+ setUserEmail(email);
138
+ setUserEmailNeedsValidation(true);
139
+ setUserEmailValidated(false);
140
+ emailNeedsValidation = true;
141
+ await telemetry.record("feature_used", { feature: "userCompletedPromptForEmailUnverified" });
142
+ }
143
+ return { emailNeedsValidation };
144
+ }
145
+ async function checkEmailStatusAndMaybeExit(options) {
146
+ const result = await checkEmailStatus(options);
147
+ if (require_logger.isCI()) return "ok";
148
+ if (result.status === EmailValidationStatus.RISKY_EMAIL || result.status === EmailValidationStatus.DISPOSABLE_EMAIL) {
149
+ require_logger.logger.error("Please use a valid work email.");
150
+ setUserEmail("");
151
+ return BAD_EMAIL_RESULT;
152
+ }
153
+ if (result.status === EmailValidationStatus.EXCEEDED_LIMIT) {
154
+ require_logger.logger.error("You have exceeded the maximum cloud inference limit. Please contact inquiries@promptfoo.dev to upgrade your account.");
155
+ process.exit(1);
156
+ }
157
+ if (result.status === EmailValidationStatus.EMAIL_VERIFICATION_REQUIRED) {
158
+ setUserEmailNeedsValidation(true);
159
+ setUserEmailValidated(false);
160
+ const message = result.message || "Your email address is not verified. Check your inbox for a verification link, then rerun the command.";
161
+ require_logger.logger.error(message, {
162
+ status: result.status,
163
+ hasEmail: result.hasEmail
164
+ });
165
+ process.exit(1);
166
+ }
167
+ if (result.status === EmailValidationStatus.SHOW_USAGE_WARNING && result.message) {
168
+ const border = "=".repeat(require_fetch.TERMINAL_MAX_WIDTH);
169
+ require_logger.logger.info(border);
170
+ require_logger.logger.warn(result.message);
171
+ require_logger.logger.info(border);
172
+ }
173
+ return "ok";
174
+ }
175
+ //#endregion
176
+ Object.defineProperty(exports, "checkEmailStatusAndMaybeExit", {
177
+ enumerable: true,
178
+ get: function() {
179
+ return checkEmailStatusAndMaybeExit;
180
+ }
181
+ });
182
+ Object.defineProperty(exports, "getAuthMethod", {
183
+ enumerable: true,
184
+ get: function() {
185
+ return getAuthMethod;
186
+ }
187
+ });
188
+ Object.defineProperty(exports, "getAuthor", {
189
+ enumerable: true,
190
+ get: function() {
191
+ return getAuthor;
192
+ }
193
+ });
194
+ Object.defineProperty(exports, "getUserEmail", {
195
+ enumerable: true,
196
+ get: function() {
197
+ return getUserEmail;
198
+ }
199
+ });
200
+ Object.defineProperty(exports, "getUserId", {
201
+ enumerable: true,
202
+ get: function() {
203
+ return getUserId;
204
+ }
205
+ });
206
+ Object.defineProperty(exports, "isLoggedIntoCloud", {
207
+ enumerable: true,
208
+ get: function() {
209
+ return isLoggedIntoCloud;
210
+ }
211
+ });
212
+ Object.defineProperty(exports, "promptForEmailUnverified", {
213
+ enumerable: true,
214
+ get: function() {
215
+ return promptForEmailUnverified;
216
+ }
217
+ });
218
+
219
+ //# sourceMappingURL=accounts-Bt1oJb1Z.cjs.map
@@ -0,0 +1,178 @@
1
+ import { r as logger, w as isCI, x as getEnvString } from "./logger-C40ZGil9.js";
2
+ import { A as TERMINAL_MAX_WIDTH, a as CloudConfig, c as writeGlobalConfig, l as writeGlobalConfigPartial, r as fetchWithTimeout, s as readGlobalConfig } from "./fetch-DQckpUFz.js";
3
+ const BAD_EMAIL_RESULT = "bad_email";
4
+ const EmailValidationStatus = {
5
+ OK: "ok",
6
+ EXCEEDED_LIMIT: "exceeded_limit",
7
+ SHOW_USAGE_WARNING: "show_usage_warning",
8
+ EMAIL_VERIFICATION_REQUIRED: "email_verification_required",
9
+ RISKY_EMAIL: "risky_email",
10
+ DISPOSABLE_EMAIL: "disposable_email"
11
+ };
12
+ const NO_EMAIL_STATUS = "no_email";
13
+ //#endregion
14
+ //#region src/globalConfig/accounts.ts
15
+ const CI_PLACEHOLDER_EMAIL = "ci-placeholder@promptfoo.dev";
16
+ function getUserId() {
17
+ let globalConfig = readGlobalConfig();
18
+ if (!globalConfig?.id) {
19
+ const newId = crypto.randomUUID();
20
+ globalConfig = {
21
+ ...globalConfig,
22
+ id: newId
23
+ };
24
+ writeGlobalConfig(globalConfig);
25
+ return newId;
26
+ }
27
+ return globalConfig.id;
28
+ }
29
+ function getUserEmail() {
30
+ return readGlobalConfig()?.account?.email || null;
31
+ }
32
+ function setUserEmail(email) {
33
+ const account = readGlobalConfig()?.account ?? {};
34
+ account.email = email;
35
+ writeGlobalConfigPartial({ account });
36
+ }
37
+ function getUserEmailNeedsValidation() {
38
+ return readGlobalConfig()?.account?.emailNeedsValidation || false;
39
+ }
40
+ function setUserEmailNeedsValidation(needsValidation) {
41
+ const account = readGlobalConfig()?.account ?? {};
42
+ account.emailNeedsValidation = needsValidation;
43
+ writeGlobalConfigPartial({ account });
44
+ }
45
+ function getUserEmailValidated() {
46
+ return readGlobalConfig()?.account?.emailValidated || false;
47
+ }
48
+ function setUserEmailValidated(validated) {
49
+ const account = readGlobalConfig()?.account ?? {};
50
+ account.emailValidated = validated;
51
+ writeGlobalConfigPartial({ account });
52
+ }
53
+ function getAuthor() {
54
+ return getEnvString("PROMPTFOO_AUTHOR") || getUserEmail() || null;
55
+ }
56
+ function isLoggedIntoCloud() {
57
+ return new CloudConfig().isEnabled();
58
+ }
59
+ /**
60
+ * Get the authentication method used for cloud access
61
+ * @returns 'api-key' | 'email' | 'none'
62
+ */
63
+ function getAuthMethod() {
64
+ const hasApiKey = new CloudConfig().isEnabled();
65
+ const hasEmail = !!getUserEmail();
66
+ if (hasApiKey && hasEmail) return "api-key";
67
+ if (hasApiKey) return "api-key";
68
+ if (hasEmail) return "email";
69
+ return "none";
70
+ }
71
+ /**
72
+ * Shared function to check email status with the promptfoo API
73
+ * Used by both CLI and server routes
74
+ */
75
+ async function checkEmailStatus(options) {
76
+ const { default: telemetry } = await import("./telemetry-Bg2WqF79.js").then((n) => n.n);
77
+ const ciMode = isCI();
78
+ const userEmail = ciMode ? CI_PLACEHOLDER_EMAIL : getUserEmail();
79
+ if (!userEmail) return {
80
+ status: NO_EMAIL_STATUS,
81
+ hasEmail: false,
82
+ message: "Redteam evals require email verification. Please enter your work email:"
83
+ };
84
+ if (ciMode) return {
85
+ status: EmailValidationStatus.OK,
86
+ hasEmail: true,
87
+ email: userEmail
88
+ };
89
+ try {
90
+ const validateParam = options?.validate ? "&validate=true" : "";
91
+ const timeout = options?.validate ? 3e3 : 500;
92
+ if (options?.validate) logger.info(`Checking email...`);
93
+ const data = await (await fetchWithTimeout(`${getEnvString("PROMPTFOO_CLOUD_API_URL", "https://api.promptfoo.app")}/api/users/status?email=${encodeURIComponent(userEmail)}${validateParam}`, void 0, timeout)).json();
94
+ if (options?.validate) if (new Set([
95
+ EmailValidationStatus.RISKY_EMAIL,
96
+ EmailValidationStatus.DISPOSABLE_EMAIL,
97
+ EmailValidationStatus.EMAIL_VERIFICATION_REQUIRED
98
+ ]).has(data.status)) {
99
+ if (data.status === EmailValidationStatus.EMAIL_VERIFICATION_REQUIRED) {
100
+ setUserEmailValidated(false);
101
+ setUserEmailNeedsValidation(true);
102
+ }
103
+ if (data.status === EmailValidationStatus.RISKY_EMAIL || data.status === EmailValidationStatus.DISPOSABLE_EMAIL) await telemetry.saveConsent(userEmail, { source: "filteredInvalidEmail" });
104
+ } else {
105
+ setUserEmailValidated(true);
106
+ await telemetry.saveConsent(userEmail, { source: "promptForEmailValidated" });
107
+ }
108
+ return {
109
+ status: data.status,
110
+ message: data.message ?? data.error,
111
+ email: userEmail,
112
+ hasEmail: true
113
+ };
114
+ } catch (e) {
115
+ logger.debug(`Failed to check user status: ${e}`);
116
+ return {
117
+ status: EmailValidationStatus.OK,
118
+ message: "Unable to verify email status, but proceeding",
119
+ email: userEmail,
120
+ hasEmail: true
121
+ };
122
+ }
123
+ }
124
+ async function promptForEmailUnverified() {
125
+ const { default: telemetry } = await import("./telemetry-Bg2WqF79.js").then((n) => n.n);
126
+ const ciMode = isCI();
127
+ const existingEmail = getUserEmail();
128
+ let email = ciMode ? CI_PLACEHOLDER_EMAIL : existingEmail;
129
+ const existingEmailNeedsValidation = !ciMode && getUserEmailNeedsValidation();
130
+ const existingEmailValidated = ciMode || getUserEmailValidated();
131
+ let emailNeedsValidation = existingEmailNeedsValidation && !existingEmailValidated;
132
+ if (!email) {
133
+ await telemetry.record("feature_used", { feature: "promptForEmailUnverified" });
134
+ const envEmail = getEnvString("PROMPTFOO_EMAIL");
135
+ if (!envEmail) throw new Error("Email verification required for red team scans. Set the PROMPTFOO_EMAIL environment variable to your work email address.");
136
+ email = envEmail;
137
+ setUserEmail(email);
138
+ setUserEmailNeedsValidation(true);
139
+ setUserEmailValidated(false);
140
+ emailNeedsValidation = true;
141
+ await telemetry.record("feature_used", { feature: "userCompletedPromptForEmailUnverified" });
142
+ }
143
+ return { emailNeedsValidation };
144
+ }
145
+ async function checkEmailStatusAndMaybeExit(options) {
146
+ const result = await checkEmailStatus(options);
147
+ if (isCI()) return "ok";
148
+ if (result.status === EmailValidationStatus.RISKY_EMAIL || result.status === EmailValidationStatus.DISPOSABLE_EMAIL) {
149
+ logger.error("Please use a valid work email.");
150
+ setUserEmail("");
151
+ return BAD_EMAIL_RESULT;
152
+ }
153
+ if (result.status === EmailValidationStatus.EXCEEDED_LIMIT) {
154
+ logger.error("You have exceeded the maximum cloud inference limit. Please contact inquiries@promptfoo.dev to upgrade your account.");
155
+ process.exit(1);
156
+ }
157
+ if (result.status === EmailValidationStatus.EMAIL_VERIFICATION_REQUIRED) {
158
+ setUserEmailNeedsValidation(true);
159
+ setUserEmailValidated(false);
160
+ const message = result.message || "Your email address is not verified. Check your inbox for a verification link, then rerun the command.";
161
+ logger.error(message, {
162
+ status: result.status,
163
+ hasEmail: result.hasEmail
164
+ });
165
+ process.exit(1);
166
+ }
167
+ if (result.status === EmailValidationStatus.SHOW_USAGE_WARNING && result.message) {
168
+ const border = "=".repeat(TERMINAL_MAX_WIDTH);
169
+ logger.info(border);
170
+ logger.warn(result.message);
171
+ logger.info(border);
172
+ }
173
+ return "ok";
174
+ }
175
+ //#endregion
176
+ export { getUserId as a, getUserEmail as i, getAuthMethod as n, isLoggedIntoCloud as o, getAuthor as r, promptForEmailUnverified as s, checkEmailStatusAndMaybeExit as t };
177
+
178
+ //# sourceMappingURL=accounts-DjOU8Rm3.js.map
@@ -0,0 +1,153 @@
1
+ import { r as logger } from "./logger-C40ZGil9.js";
2
+ import { a as isCacheEnabled, i as getCache } from "./cache-BkrqU5Ba.js";
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import dedent from "dedent";
6
+ import crypto from "crypto";
7
+ //#region src/providers/agentic-utils.ts
8
+ /**
9
+ * Shared utilities for agentic providers (Claude Agent SDK, OpenCode SDK, etc.)
10
+ *
11
+ * These utilities handle common functionality needed by coding agent providers:
12
+ * - Working directory fingerprinting for cache key generation
13
+ * - Response caching with fingerprint support
14
+ */
15
+ /**
16
+ * Timeout for working directory fingerprint generation (ms)
17
+ * Prevents hanging on extremely large directories
18
+ */
19
+ const FINGERPRINT_TIMEOUT_MS = 2e3;
20
+ /**
21
+ * Get a fingerprint for a working directory to use as a cache key.
22
+ * Checks directory mtime and descendant file mtimes recursively.
23
+ *
24
+ * This allows for caching prompts that use the same working directory
25
+ * when the files haven't changed.
26
+ *
27
+ * @param workingDir - Absolute path to the working directory
28
+ * @returns SHA-256 hash fingerprint of the directory state
29
+ * @throws Error if fingerprinting times out or directory is inaccessible
30
+ */
31
+ async function getWorkingDirFingerprint(workingDir) {
32
+ const dirMtime = fs.statSync(workingDir).mtimeMs;
33
+ const startTime = Date.now();
34
+ const getAllFiles = (dir, files = []) => {
35
+ if (Date.now() - startTime > FINGERPRINT_TIMEOUT_MS) throw new Error("Working directory fingerprint timed out");
36
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
37
+ for (const entry of entries) {
38
+ const fullPath = path.join(dir, entry.name);
39
+ if (entry.isDirectory()) getAllFiles(fullPath, files);
40
+ else if (entry.isFile()) files.push(fullPath);
41
+ }
42
+ return files;
43
+ };
44
+ const fingerprintData = `dir:${dirMtime};files:${getAllFiles(workingDir).map((file) => {
45
+ const stat = fs.statSync(file);
46
+ return `${path.relative(workingDir, file)}:${stat.mtimeMs}`;
47
+ }).sort().join(",")}`;
48
+ return crypto.createHash("sha256").update(fingerprintData).digest("hex");
49
+ }
50
+ /**
51
+ * Generate a cache key from arbitrary data using SHA-256 hash
52
+ *
53
+ * @param prefix - Cache key prefix (provider identifier)
54
+ * @param data - Data to hash for the cache key
55
+ * @returns Prefixed SHA-256 hash cache key
56
+ */
57
+ function generateCacheKey(prefix, data) {
58
+ const stringified = JSON.stringify(data);
59
+ return `${prefix}:${crypto.createHash("sha256").update(stringified).digest("hex")}`;
60
+ }
61
+ /**
62
+ * Initialize cache and check for cached response
63
+ *
64
+ * This handles the common caching pattern used by agentic providers:
65
+ * 1. Check if caching is enabled
66
+ * 2. Generate working directory fingerprint if needed
67
+ * 3. Generate cache key
68
+ * 4. Return cache configuration for use by the provider
69
+ *
70
+ * @param options - Cache options including prefix and working directory
71
+ * @param cacheKeyData - Data to include in the cache key
72
+ * @returns Cache configuration and optional cached response
73
+ */
74
+ async function initializeAgenticCache(options, cacheKeyData) {
75
+ if (!isCacheEnabled()) return {
76
+ shouldCache: false,
77
+ shouldReadCache: false,
78
+ shouldWriteCache: false
79
+ };
80
+ if (options.mcp && !options.cacheMcp) return {
81
+ shouldCache: false,
82
+ shouldReadCache: false,
83
+ shouldWriteCache: false
84
+ };
85
+ let workingDirFingerprint = null;
86
+ if (options.workingDir) try {
87
+ workingDirFingerprint = await getWorkingDirFingerprint(options.workingDir);
88
+ } catch (error) {
89
+ logger.error(dedent`Error getting working directory fingerprint for cache key - ${options.workingDir}: ${String(error)}
90
+
91
+ Caching is disabled.`);
92
+ return {
93
+ shouldCache: false,
94
+ shouldReadCache: false,
95
+ shouldWriteCache: false
96
+ };
97
+ }
98
+ const cache = await getCache();
99
+ const cacheKey = generateCacheKey(options.cacheKeyPrefix, {
100
+ ...cacheKeyData,
101
+ workingDirFingerprint,
102
+ ...options.mcp ? { mcp: options.mcp } : {}
103
+ });
104
+ return {
105
+ shouldCache: true,
106
+ shouldReadCache: !options.bustCache,
107
+ shouldWriteCache: true,
108
+ cache,
109
+ cacheKey,
110
+ workingDirFingerprint
111
+ };
112
+ }
113
+ /**
114
+ * Try to get a cached response
115
+ *
116
+ * @param cacheResult - Result from initializeAgenticCache
117
+ * @param debugContext - Context for debug logging (e.g., prompt preview)
118
+ * @returns Cached ProviderResponse if found, undefined otherwise
119
+ */
120
+ async function getCachedResponse(cacheResult, debugContext) {
121
+ if (!cacheResult.shouldReadCache || !cacheResult.cache || !cacheResult.cacheKey) return;
122
+ try {
123
+ const cachedResponse = await cacheResult.cache.get(cacheResult.cacheKey);
124
+ if (cachedResponse) {
125
+ logger.debug(`Returning cached response${debugContext ? ` for ${debugContext}` : ""} (cache key: ${cacheResult.cacheKey})`);
126
+ return {
127
+ ...JSON.parse(cachedResponse),
128
+ cached: true
129
+ };
130
+ }
131
+ } catch (error) {
132
+ logger.error(`Error getting cached response: ${String(error)}`);
133
+ }
134
+ }
135
+ /**
136
+ * Cache a provider response
137
+ *
138
+ * @param cacheResult - Result from initializeAgenticCache
139
+ * @param response - The ProviderResponse to cache
140
+ * @param debugContext - Context for debug logging
141
+ */
142
+ async function cacheResponse(cacheResult, response, debugContext) {
143
+ if (!cacheResult.shouldWriteCache || !cacheResult.cache || !cacheResult.cacheKey) return;
144
+ try {
145
+ await cacheResult.cache.set(cacheResult.cacheKey, JSON.stringify(response));
146
+ } catch (error) {
147
+ logger.error(`Error caching response${debugContext ? ` for ${debugContext}` : ""}: ${String(error)}`);
148
+ }
149
+ }
150
+ //#endregion
151
+ export { initializeAgenticCache as i, generateCacheKey as n, getCachedResponse as r, cacheResponse as t };
152
+
153
+ //# sourceMappingURL=agentic-utils-D03IiXQc.js.map