@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.
- package/LICENSE +19 -0
- package/dist/src/accounts-Bt1oJb1Z.cjs +219 -0
- package/dist/src/accounts-DjOU8Rm3.js +178 -0
- package/dist/src/agentic-utils-D03IiXQc.js +153 -0
- package/dist/src/agentic-utils-Dh7xaMQM.cjs +180 -0
- package/dist/src/agents-C6BIMlZa.js +231 -0
- package/dist/src/agents-DvIpNX1L.cjs +666 -0
- package/dist/src/agents-ZP0RP9vV.cjs +231 -0
- package/dist/src/agents-maJXdjbR.js +665 -0
- package/dist/src/aimlapi-BTbQjG2E.cjs +30 -0
- package/dist/src/aimlapi-CwMxqfXP.js +30 -0
- package/dist/src/audio-BBUdvsde.cjs +97 -0
- package/dist/src/audio-D5DPZ7I-.js +97 -0
- package/dist/src/base-BEysXrkq.cjs +222 -0
- package/dist/src/base-C451JQfq.js +193 -0
- package/dist/src/blobs-BY8MDmpo.js +230 -0
- package/dist/src/blobs-BgcNn97m.cjs +256 -0
- package/dist/src/cache-BBE_lsTA.cjs +4 -0
- package/dist/src/cache-BkrqU5Ba.js +237 -0
- package/dist/src/cache-DsCxFlsZ.cjs +297 -0
- package/dist/src/chat-CPJWDP6a.cjs +289 -0
- package/dist/src/chat-CXX3xzkk.cjs +811 -0
- package/dist/src/chat-CcDgZFJ4.js +787 -0
- package/dist/src/chat-Dz5ZeGO2.js +289 -0
- package/dist/src/chatkit-Dw0mKkML.cjs +1158 -0
- package/dist/src/chatkit-swAIVuea.js +1157 -0
- package/dist/src/chunk-DEq-mXcV.js +15 -0
- package/dist/src/claude-agent-sdk-BXZJtOg6.js +379 -0
- package/dist/src/claude-agent-sdk-CkfyjDoG.cjs +383 -0
- package/dist/src/cloudflare-ai-BzpJcqUH.js +161 -0
- package/dist/src/cloudflare-ai-Cmy_R1y2.cjs +161 -0
- package/dist/src/cloudflare-gateway-B9tVQKok.cjs +272 -0
- package/dist/src/cloudflare-gateway-DrD3ew3H.js +272 -0
- package/dist/src/codex-sdk-Dezj9Nwm.js +1056 -0
- package/dist/src/codex-sdk-Dl9D4k5B.cjs +1060 -0
- package/dist/src/cometapi-C-9YvCHC.js +54 -0
- package/dist/src/cometapi-DHgDKoO2.cjs +54 -0
- package/dist/src/completion-B8Ctyxpr.js +120 -0
- package/dist/src/completion-Cxrt08sj.cjs +131 -0
- package/dist/src/createHash-BwgE13yv.cjs +27 -0
- package/dist/src/createHash-DmPQkvBh.js +15 -0
- package/dist/src/docker-BiqcTwLv.js +80 -0
- package/dist/src/docker-C7tEJnP-.cjs +80 -0
- package/dist/src/esm-C62Zofr1.cjs +409 -0
- package/dist/src/esm-DMVc93eh.js +379 -0
- package/dist/src/evalResult-C3NJPQOo.cjs +301 -0
- package/dist/src/evalResult-C7JJAPBb.js +295 -0
- package/dist/src/evalResult-DoVTZZWI.cjs +2 -0
- package/dist/src/extractor-DnMD3fwt.cjs +391 -0
- package/dist/src/extractor-DtlL28vL.js +374 -0
- package/dist/src/fetch-BTxakTSg.cjs +1133 -0
- package/dist/src/fetch-DQckpUFz.js +928 -0
- package/dist/src/fileExtensions-DnqA1y9x.js +85 -0
- package/dist/src/fileExtensions-bYh77CN8.cjs +114 -0
- package/dist/src/genaiTracer-CyZrmaK0.cjs +268 -0
- package/dist/src/genaiTracer-D3fD9dNV.js +256 -0
- package/dist/src/graders-BNscxFrU.js +13644 -0
- package/dist/src/graders-D2oE9Msq.js +2 -0
- package/dist/src/graders-c0Ez_w-9.cjs +2 -0
- package/dist/src/graders-d0F2M3e9.cjs +14056 -0
- package/dist/src/image-0ZhE0VlR.cjs +280 -0
- package/dist/src/image-CWE1pdNv.js +257 -0
- package/dist/src/image-D9ZK6hwL.js +163 -0
- package/dist/src/image-DKZgZITg.cjs +163 -0
- package/dist/src/index.cjs +11366 -0
- package/dist/src/index.d.cts +19640 -0
- package/dist/src/index.d.ts +19641 -0
- package/dist/src/index.js +11306 -0
- package/dist/src/invariant-Ddh24eXh.js +25 -0
- package/dist/src/invariant-kfQ8Bu82.cjs +30 -0
- package/dist/src/knowledgeBase-BgPyGFUd.cjs +122 -0
- package/dist/src/knowledgeBase-DyHilYaP.js +122 -0
- package/dist/src/litellm-CyMeneHS.js +135 -0
- package/dist/src/litellm-DWDF73yF.cjs +135 -0
- package/dist/src/logger-C40ZGil9.js +717 -0
- package/dist/src/logger-DyfK9PBt.cjs +917 -0
- package/dist/src/luma-ray-BAU9X_ep.cjs +315 -0
- package/dist/src/luma-ray-nwVseBbv.js +313 -0
- package/dist/src/messages-B5ADWTTv.js +245 -0
- package/dist/src/messages-BCnZfqrS.cjs +257 -0
- package/dist/src/meteor-DLZZ3osF.cjs +134 -0
- package/dist/src/meteor-DUiCJRC-.js +134 -0
- package/dist/src/modelslab-00cveB8L.cjs +163 -0
- package/dist/src/modelslab-D9sCU_L7.js +163 -0
- package/dist/src/nova-reel-CTapvqYH.js +276 -0
- package/dist/src/nova-reel-DlWuuroF.cjs +278 -0
- package/dist/src/nova-sonic-5UPWfeMv.cjs +363 -0
- package/dist/src/nova-sonic-BhSwQNym.js +363 -0
- package/dist/src/openai-BWrJK9d8.cjs +52 -0
- package/dist/src/openai-DumO8WQn.js +47 -0
- package/dist/src/openclaw-B8brrjC_.cjs +577 -0
- package/dist/src/openclaw-Bkayww9q.js +571 -0
- package/dist/src/opencode-sdk-7xjoDNiM.cjs +562 -0
- package/dist/src/opencode-sdk-SGwAPxht.js +558 -0
- package/dist/src/otlpReceiver-CoAHfAN9.cjs +15 -0
- package/dist/src/otlpReceiver-oO3EQwI9.js +14 -0
- package/dist/src/providerRegistry-4yjhaEM8.js +45 -0
- package/dist/src/providerRegistry-DhV4rJIc.cjs +50 -0
- package/dist/src/providers-B5RJVG-7.cjs +33609 -0
- package/dist/src/providers-BdmZCLzV.js +33262 -0
- package/dist/src/providers-CxtRxn8e.js +2 -0
- package/dist/src/providers-DnQLNbx1.cjs +3 -0
- package/dist/src/pythonUtils-BD0druiM.cjs +275 -0
- package/dist/src/pythonUtils-IBhn5YGR.js +249 -0
- package/dist/src/quiverai-BDOwZBsM.cjs +213 -0
- package/dist/src/quiverai-D3JTF5lD.js +213 -0
- package/dist/src/responses-B2LCDCXZ.js +667 -0
- package/dist/src/responses-BvNm4Xv9.cjs +685 -0
- package/dist/src/rubyUtils-B0NwnfpY.cjs +245 -0
- package/dist/src/rubyUtils-BroxzZ7c.cjs +2 -0
- package/dist/src/rubyUtils-hqVw5UvJ.js +222 -0
- package/dist/src/sagemaker-Cno2V-Sx.js +689 -0
- package/dist/src/sagemaker-fV_KUgs5.cjs +691 -0
- package/dist/src/server-BOuAXb06.cjs +238 -0
- package/dist/src/server-CtI-EWzm.cjs +2 -0
- package/dist/src/server-Cy3DZymt.js +189 -0
- package/dist/src/slack-CP8xBePa.js +135 -0
- package/dist/src/slack-DSQ1yXVb.cjs +135 -0
- package/dist/src/store-BwDDaBjb.cjs +246 -0
- package/dist/src/store-DcbLC593.cjs +2 -0
- package/dist/src/store-IGpqMIkv.js +240 -0
- package/dist/src/tables-3Q2cL7So.cjs +373 -0
- package/dist/src/tables-Bi2fjr4W.js +288 -0
- package/dist/src/telemetry-Bg2WqF79.js +161 -0
- package/dist/src/telemetry-D0x6u5kX.cjs +166 -0
- package/dist/src/telemetry-DXNimrI0.cjs +2 -0
- package/dist/src/text-B_UCRPp2.js +22 -0
- package/dist/src/text-CW1cyrwj.cjs +33 -0
- package/dist/src/tokenUsageUtils-NYT-WKS6.js +138 -0
- package/dist/src/tokenUsageUtils-bVa1ga6f.cjs +173 -0
- package/dist/src/transcription-Cl_W16Pr.js +122 -0
- package/dist/src/transcription-yt1EecY8.cjs +124 -0
- package/dist/src/transform-BCtGrl_W.cjs +228 -0
- package/dist/src/transform-Bv6gG2MJ.cjs +1688 -0
- package/dist/src/transform-CY1wbpRy.js +1507 -0
- package/dist/src/transform-DU8rUL9P.cjs +2 -0
- package/dist/src/transform-yWaShiKr.js +216 -0
- package/dist/src/transformersAvailability-BGkzavwb.js +35 -0
- package/dist/src/transformersAvailability-DKoRtQLy.cjs +35 -0
- package/dist/src/types-5aqHpBwE.cjs +3769 -0
- package/dist/src/types-Bn6D9c4U.js +3300 -0
- package/dist/src/util-BkKlTkI2.js +293 -0
- package/dist/src/util-CTh0bfOm.cjs +1119 -0
- package/dist/src/util-D17oBwo7.cjs +328 -0
- package/dist/src/util-DsS_-v4p.js +613 -0
- package/dist/src/util-DuntT1Ga.js +951 -0
- package/dist/src/util-aWjdCYMI.cjs +667 -0
- package/dist/src/utils-CisQwpjA.js +94 -0
- package/dist/src/utils-yWamDvmz.cjs +123 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/drizzle/0000_lush_hellion.sql +36 -0
- package/drizzle/0001_wide_calypso.sql +3 -0
- package/drizzle/0002_tidy_juggernaut.sql +1 -0
- package/drizzle/0003_lively_naoko.sql +8 -0
- package/drizzle/0004_minor_peter_quill.sql +19 -0
- package/drizzle/0005_silky_millenium_guard.sql +2 -0
- package/drizzle/0006_harsh_caretaker.sql +42 -0
- package/drizzle/0007_cloudy_wong.sql +1 -0
- package/drizzle/0008_broad_boomer.sql +2 -0
- package/drizzle/0009_strong_marten_broadcloak.sql +19 -0
- package/drizzle/0010_needy_bishop.sql +11 -0
- package/drizzle/0011_moaning_millenium_guard.sql +1 -0
- package/drizzle/0012_late_marten_broadcloak.sql +2 -0
- package/drizzle/0013_previous_dormammu.sql +9 -0
- package/drizzle/0014_lazy_captain_universe.sql +2 -0
- package/drizzle/0015_zippy_wallop.sql +29 -0
- package/drizzle/0016_jazzy_zemo.sql +2 -0
- package/drizzle/0017_reflective_praxagora.sql +4 -0
- package/drizzle/0018_fat_vanisher.sql +22 -0
- package/drizzle/0019_new_clint_barton.sql +8 -0
- package/drizzle/0020_skinny_maverick.sql +1 -0
- package/drizzle/0021_mysterious_madelyne_pryor.sql +13 -0
- package/drizzle/0022_sleepy_ultimo.sql +25 -0
- package/drizzle/0023_wooden_mandrill.sql +2 -0
- package/drizzle/AGENTS.md +68 -0
- package/drizzle/CLAUDE.md +1 -0
- package/drizzle/meta/0000_snapshot.json +221 -0
- package/drizzle/meta/0001_snapshot.json +214 -0
- package/drizzle/meta/0002_snapshot.json +221 -0
- package/drizzle/meta/0005_snapshot.json +369 -0
- package/drizzle/meta/0006_snapshot.json +638 -0
- package/drizzle/meta/0007_snapshot.json +640 -0
- package/drizzle/meta/0008_snapshot.json +649 -0
- package/drizzle/meta/0009_snapshot.json +554 -0
- package/drizzle/meta/0010_snapshot.json +619 -0
- package/drizzle/meta/0011_snapshot.json +627 -0
- package/drizzle/meta/0012_snapshot.json +639 -0
- package/drizzle/meta/0013_snapshot.json +717 -0
- package/drizzle/meta/0014_snapshot.json +717 -0
- package/drizzle/meta/0015_snapshot.json +897 -0
- package/drizzle/meta/0016_snapshot.json +1031 -0
- package/drizzle/meta/0018_snapshot.json +1210 -0
- package/drizzle/meta/0019_snapshot.json +1165 -0
- package/drizzle/meta/0020_snapshot.json +1232 -0
- package/drizzle/meta/0021_snapshot.json +1311 -0
- package/drizzle/meta/0022_snapshot.json +1481 -0
- package/drizzle/meta/0023_snapshot.json +1496 -0
- package/drizzle/meta/_journal.json +174 -0
- package/package.json +240 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
//#region src/util/fileExtensions.ts
|
|
2
|
+
/**
|
|
3
|
+
* Array of supported JavaScript and TypeScript file extensions
|
|
4
|
+
*/
|
|
5
|
+
const JAVASCRIPT_EXTENSIONS = [
|
|
6
|
+
"js",
|
|
7
|
+
"cjs",
|
|
8
|
+
"mjs",
|
|
9
|
+
"ts",
|
|
10
|
+
"cts",
|
|
11
|
+
"mts"
|
|
12
|
+
];
|
|
13
|
+
/**
|
|
14
|
+
* Checks if a file is a JavaScript or TypeScript file based on its extension.
|
|
15
|
+
*
|
|
16
|
+
* @param filePath - The path of the file to check.
|
|
17
|
+
* @returns True if the file has a JavaScript or TypeScript extension, false otherwise.
|
|
18
|
+
*/
|
|
19
|
+
function isJavascriptFile(filePath) {
|
|
20
|
+
return new RegExp(`\\.(${JAVASCRIPT_EXTENSIONS.join("|")})$`).test(filePath);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Checks if a file is an image file based on its extension. Non-exhaustive list.
|
|
24
|
+
*
|
|
25
|
+
* @param filePath - The path of the file to check.
|
|
26
|
+
* @returns True if the file has an image extension, false otherwise.
|
|
27
|
+
*/
|
|
28
|
+
function isImageFile(filePath) {
|
|
29
|
+
const imageExtensions = [
|
|
30
|
+
"jpg",
|
|
31
|
+
"jpeg",
|
|
32
|
+
"png",
|
|
33
|
+
"gif",
|
|
34
|
+
"bmp",
|
|
35
|
+
"webp",
|
|
36
|
+
"svg"
|
|
37
|
+
];
|
|
38
|
+
const fileExtension = filePath.split(".").pop()?.toLowerCase() || "";
|
|
39
|
+
return imageExtensions.includes(fileExtension);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Checks if a file is a video file based on its extension. Non-exhaustive list.
|
|
43
|
+
*
|
|
44
|
+
* @param filePath - The path of the file to check.
|
|
45
|
+
* @returns True if the file has a video extension, false otherwise.
|
|
46
|
+
*/
|
|
47
|
+
function isVideoFile(filePath) {
|
|
48
|
+
const videoExtensions = [
|
|
49
|
+
"mp4",
|
|
50
|
+
"webm",
|
|
51
|
+
"ogg",
|
|
52
|
+
"mov",
|
|
53
|
+
"avi",
|
|
54
|
+
"wmv",
|
|
55
|
+
"mkv",
|
|
56
|
+
"m4v"
|
|
57
|
+
];
|
|
58
|
+
const fileExtension = filePath.split(".").pop()?.toLowerCase() || "";
|
|
59
|
+
return videoExtensions.includes(fileExtension);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Checks if a file is an audio file based on its extension. Non-exhaustive list.
|
|
63
|
+
*
|
|
64
|
+
* @param filePath - The path of the file to check.
|
|
65
|
+
* @returns True if the file has an audio extension, false otherwise.
|
|
66
|
+
*/
|
|
67
|
+
function isAudioFile(filePath) {
|
|
68
|
+
const audioExtensions = [
|
|
69
|
+
"wav",
|
|
70
|
+
"mp3",
|
|
71
|
+
"ogg",
|
|
72
|
+
"aac",
|
|
73
|
+
"m4a",
|
|
74
|
+
"flac",
|
|
75
|
+
"wma",
|
|
76
|
+
"aiff",
|
|
77
|
+
"opus"
|
|
78
|
+
];
|
|
79
|
+
const fileExtension = filePath.split(".").pop()?.toLowerCase() || "";
|
|
80
|
+
return audioExtensions.includes(fileExtension);
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
export { isVideoFile as a, isJavascriptFile as i, isAudioFile as n, isImageFile as r, JAVASCRIPT_EXTENSIONS as t };
|
|
84
|
+
|
|
85
|
+
//# sourceMappingURL=fileExtensions-DnqA1y9x.js.map
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
//#region src/util/fileExtensions.ts
|
|
2
|
+
/**
|
|
3
|
+
* Array of supported JavaScript and TypeScript file extensions
|
|
4
|
+
*/
|
|
5
|
+
const JAVASCRIPT_EXTENSIONS = [
|
|
6
|
+
"js",
|
|
7
|
+
"cjs",
|
|
8
|
+
"mjs",
|
|
9
|
+
"ts",
|
|
10
|
+
"cts",
|
|
11
|
+
"mts"
|
|
12
|
+
];
|
|
13
|
+
/**
|
|
14
|
+
* Checks if a file is a JavaScript or TypeScript file based on its extension.
|
|
15
|
+
*
|
|
16
|
+
* @param filePath - The path of the file to check.
|
|
17
|
+
* @returns True if the file has a JavaScript or TypeScript extension, false otherwise.
|
|
18
|
+
*/
|
|
19
|
+
function isJavascriptFile(filePath) {
|
|
20
|
+
return new RegExp(`\\.(${JAVASCRIPT_EXTENSIONS.join("|")})$`).test(filePath);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Checks if a file is an image file based on its extension. Non-exhaustive list.
|
|
24
|
+
*
|
|
25
|
+
* @param filePath - The path of the file to check.
|
|
26
|
+
* @returns True if the file has an image extension, false otherwise.
|
|
27
|
+
*/
|
|
28
|
+
function isImageFile(filePath) {
|
|
29
|
+
const imageExtensions = [
|
|
30
|
+
"jpg",
|
|
31
|
+
"jpeg",
|
|
32
|
+
"png",
|
|
33
|
+
"gif",
|
|
34
|
+
"bmp",
|
|
35
|
+
"webp",
|
|
36
|
+
"svg"
|
|
37
|
+
];
|
|
38
|
+
const fileExtension = filePath.split(".").pop()?.toLowerCase() || "";
|
|
39
|
+
return imageExtensions.includes(fileExtension);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Checks if a file is a video file based on its extension. Non-exhaustive list.
|
|
43
|
+
*
|
|
44
|
+
* @param filePath - The path of the file to check.
|
|
45
|
+
* @returns True if the file has a video extension, false otherwise.
|
|
46
|
+
*/
|
|
47
|
+
function isVideoFile(filePath) {
|
|
48
|
+
const videoExtensions = [
|
|
49
|
+
"mp4",
|
|
50
|
+
"webm",
|
|
51
|
+
"ogg",
|
|
52
|
+
"mov",
|
|
53
|
+
"avi",
|
|
54
|
+
"wmv",
|
|
55
|
+
"mkv",
|
|
56
|
+
"m4v"
|
|
57
|
+
];
|
|
58
|
+
const fileExtension = filePath.split(".").pop()?.toLowerCase() || "";
|
|
59
|
+
return videoExtensions.includes(fileExtension);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Checks if a file is an audio file based on its extension. Non-exhaustive list.
|
|
63
|
+
*
|
|
64
|
+
* @param filePath - The path of the file to check.
|
|
65
|
+
* @returns True if the file has an audio extension, false otherwise.
|
|
66
|
+
*/
|
|
67
|
+
function isAudioFile(filePath) {
|
|
68
|
+
const audioExtensions = [
|
|
69
|
+
"wav",
|
|
70
|
+
"mp3",
|
|
71
|
+
"ogg",
|
|
72
|
+
"aac",
|
|
73
|
+
"m4a",
|
|
74
|
+
"flac",
|
|
75
|
+
"wma",
|
|
76
|
+
"aiff",
|
|
77
|
+
"opus"
|
|
78
|
+
];
|
|
79
|
+
const fileExtension = filePath.split(".").pop()?.toLowerCase() || "";
|
|
80
|
+
return audioExtensions.includes(fileExtension);
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
Object.defineProperty(exports, "JAVASCRIPT_EXTENSIONS", {
|
|
84
|
+
enumerable: true,
|
|
85
|
+
get: function() {
|
|
86
|
+
return JAVASCRIPT_EXTENSIONS;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
Object.defineProperty(exports, "isAudioFile", {
|
|
90
|
+
enumerable: true,
|
|
91
|
+
get: function() {
|
|
92
|
+
return isAudioFile;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
Object.defineProperty(exports, "isImageFile", {
|
|
96
|
+
enumerable: true,
|
|
97
|
+
get: function() {
|
|
98
|
+
return isImageFile;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
Object.defineProperty(exports, "isJavascriptFile", {
|
|
102
|
+
enumerable: true,
|
|
103
|
+
get: function() {
|
|
104
|
+
return isJavascriptFile;
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
Object.defineProperty(exports, "isVideoFile", {
|
|
108
|
+
enumerable: true,
|
|
109
|
+
get: function() {
|
|
110
|
+
return isVideoFile;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
//# sourceMappingURL=fileExtensions-bYh77CN8.cjs.map
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
require("./logger-DyfK9PBt.cjs");
|
|
2
|
+
let _opentelemetry_api = require("@opentelemetry/api");
|
|
3
|
+
//#region src/tracing/genaiTracer.ts
|
|
4
|
+
const TRACER_NAME = "promptfoo.providers";
|
|
5
|
+
const TRACER_VERSION = "1.0.0";
|
|
6
|
+
const GenAIAttributes = {
|
|
7
|
+
SYSTEM: "gen_ai.system",
|
|
8
|
+
OPERATION_NAME: "gen_ai.operation.name",
|
|
9
|
+
REQUEST_MODEL: "gen_ai.request.model",
|
|
10
|
+
REQUEST_MAX_TOKENS: "gen_ai.request.max_tokens",
|
|
11
|
+
REQUEST_TEMPERATURE: "gen_ai.request.temperature",
|
|
12
|
+
REQUEST_TOP_P: "gen_ai.request.top_p",
|
|
13
|
+
REQUEST_TOP_K: "gen_ai.request.top_k",
|
|
14
|
+
REQUEST_STOP_SEQUENCES: "gen_ai.request.stop_sequences",
|
|
15
|
+
REQUEST_FREQUENCY_PENALTY: "gen_ai.request.frequency_penalty",
|
|
16
|
+
REQUEST_PRESENCE_PENALTY: "gen_ai.request.presence_penalty",
|
|
17
|
+
RESPONSE_MODEL: "gen_ai.response.model",
|
|
18
|
+
RESPONSE_ID: "gen_ai.response.id",
|
|
19
|
+
RESPONSE_FINISH_REASONS: "gen_ai.response.finish_reasons",
|
|
20
|
+
USAGE_INPUT_TOKENS: "gen_ai.usage.input_tokens",
|
|
21
|
+
USAGE_OUTPUT_TOKENS: "gen_ai.usage.output_tokens",
|
|
22
|
+
USAGE_TOTAL_TOKENS: "gen_ai.usage.total_tokens",
|
|
23
|
+
USAGE_CACHED_TOKENS: "gen_ai.usage.cached_tokens",
|
|
24
|
+
USAGE_REASONING_TOKENS: "gen_ai.usage.reasoning_tokens",
|
|
25
|
+
USAGE_ACCEPTED_PREDICTION_TOKENS: "gen_ai.usage.accepted_prediction_tokens",
|
|
26
|
+
USAGE_REJECTED_PREDICTION_TOKENS: "gen_ai.usage.rejected_prediction_tokens"
|
|
27
|
+
};
|
|
28
|
+
const PromptfooAttributes = {
|
|
29
|
+
PROVIDER_ID: "promptfoo.provider.id",
|
|
30
|
+
EVAL_ID: "promptfoo.eval.id",
|
|
31
|
+
TEST_INDEX: "promptfoo.test.index",
|
|
32
|
+
PROMPT_LABEL: "promptfoo.prompt.label",
|
|
33
|
+
CACHE_HIT: "promptfoo.cache_hit",
|
|
34
|
+
REQUEST_BODY: "promptfoo.request.body",
|
|
35
|
+
RESPONSE_BODY: "promptfoo.response.body"
|
|
36
|
+
};
|
|
37
|
+
/** Maximum length for request/response body attributes (characters) */
|
|
38
|
+
const MAX_BODY_LENGTH = 4096;
|
|
39
|
+
/**
|
|
40
|
+
* Patterns to redact from request/response bodies for security.
|
|
41
|
+
* These patterns match common API key and secret formats.
|
|
42
|
+
*/
|
|
43
|
+
const SENSITIVE_PATTERNS = [
|
|
44
|
+
{
|
|
45
|
+
pattern: /\b(sk-[a-zA-Z0-9_-]{20,})/g,
|
|
46
|
+
replacement: "<REDACTED_API_KEY>"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
pattern: /\b(pk-[a-zA-Z0-9_-]{20,})/g,
|
|
50
|
+
replacement: "<REDACTED_API_KEY>"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
pattern: /\b(api[_-]?key["']?\s*[:=]\s*["']?)([a-zA-Z0-9_-]{16,})/gi,
|
|
54
|
+
replacement: "$1<REDACTED>"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
pattern: /\b(secret["']?\s*[:=]\s*["']?)([a-zA-Z0-9_-]{16,})/gi,
|
|
58
|
+
replacement: "$1<REDACTED>"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
pattern: /\b(token["']?\s*[:=]\s*["']?)([a-zA-Z0-9_-]{16,})/gi,
|
|
62
|
+
replacement: "$1<REDACTED>"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
pattern: /\b(password["']?\s*[:=]\s*["']?)([^\s"',}{]+)/gi,
|
|
66
|
+
replacement: "$1<REDACTED>"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
pattern: /(Authorization["']?\s*[:=]\s*["']?)(Bearer\s+)?([a-zA-Z0-9_.-]{16,})/gi,
|
|
70
|
+
replacement: "$1$2<REDACTED>"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
pattern: /\b(AKIA[A-Z0-9]{16})/g,
|
|
74
|
+
replacement: "<REDACTED_AWS_KEY>"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
pattern: /\b([a-zA-Z0-9/+=]{40})/g,
|
|
78
|
+
replacement: (match) => {
|
|
79
|
+
if (/^[A-Za-z0-9+/=]{40}$/.test(match) && match.includes("/")) return "<REDACTED_SECRET>";
|
|
80
|
+
return match;
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
pattern: /\b[a-f0-9]{64,}\b/gi,
|
|
85
|
+
replacement: "<REDACTED_HASH>"
|
|
86
|
+
}
|
|
87
|
+
];
|
|
88
|
+
/**
|
|
89
|
+
* Get the tracer instance for GenAI operations.
|
|
90
|
+
*/
|
|
91
|
+
function getGenAITracer() {
|
|
92
|
+
return _opentelemetry_api.trace.getTracer(TRACER_NAME, TRACER_VERSION);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Execute a function within a GenAI span.
|
|
96
|
+
*
|
|
97
|
+
* This wrapper:
|
|
98
|
+
* 1. Creates a span with GenAI semantic conventions
|
|
99
|
+
* 2. Sets request attributes before execution
|
|
100
|
+
* 3. Executes the provided function
|
|
101
|
+
* 4. Sets response attributes (including token usage) after execution
|
|
102
|
+
* 5. Handles errors and sets appropriate span status
|
|
103
|
+
*
|
|
104
|
+
* @param ctx - GenAI span context with request information
|
|
105
|
+
* @param fn - The async function to execute (typically the API call)
|
|
106
|
+
* @param resultExtractor - Optional function to extract result data from the return value
|
|
107
|
+
* @returns The return value from fn
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```typescript
|
|
111
|
+
* const response = await withGenAISpan(
|
|
112
|
+
* {
|
|
113
|
+
* system: 'openai',
|
|
114
|
+
* operationName: 'chat',
|
|
115
|
+
* model: 'gpt-4',
|
|
116
|
+
* providerId: 'openai:gpt-4',
|
|
117
|
+
* },
|
|
118
|
+
* async (span) => {
|
|
119
|
+
* return await openai.chat.completions.create({...});
|
|
120
|
+
* },
|
|
121
|
+
* (response) => ({
|
|
122
|
+
* tokenUsage: {
|
|
123
|
+
* prompt: response.usage?.prompt_tokens,
|
|
124
|
+
* completion: response.usage?.completion_tokens,
|
|
125
|
+
* },
|
|
126
|
+
* responseId: response.id,
|
|
127
|
+
* })
|
|
128
|
+
* );
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
async function withGenAISpan(ctx, fn, resultExtractor) {
|
|
132
|
+
const tracer = getGenAITracer();
|
|
133
|
+
const spanName = `${ctx.operationName} ${ctx.model}`;
|
|
134
|
+
let parentContext = _opentelemetry_api.context.active();
|
|
135
|
+
if (ctx.traceparent) {
|
|
136
|
+
const carrier = { traceparent: ctx.traceparent };
|
|
137
|
+
parentContext = _opentelemetry_api.propagation.extract(_opentelemetry_api.ROOT_CONTEXT, carrier);
|
|
138
|
+
}
|
|
139
|
+
const spanCallback = async (span) => {
|
|
140
|
+
try {
|
|
141
|
+
const value = await fn(span);
|
|
142
|
+
if (resultExtractor) setGenAIResponseAttributes(span, resultExtractor(value), ctx.sanitizeBodies);
|
|
143
|
+
const valueAsRecord = value;
|
|
144
|
+
if (valueAsRecord && typeof valueAsRecord.error === "string" && valueAsRecord.error) span.setStatus({
|
|
145
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
146
|
+
message: valueAsRecord.error
|
|
147
|
+
});
|
|
148
|
+
else span.setStatus({ code: _opentelemetry_api.SpanStatusCode.OK });
|
|
149
|
+
return value;
|
|
150
|
+
} catch (error) {
|
|
151
|
+
span.setStatus({
|
|
152
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
153
|
+
message: error instanceof Error ? error.message : String(error)
|
|
154
|
+
});
|
|
155
|
+
if (error instanceof Error) span.recordException(error);
|
|
156
|
+
throw error;
|
|
157
|
+
} finally {
|
|
158
|
+
span.end();
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
return tracer.startActiveSpan(spanName, {
|
|
162
|
+
kind: _opentelemetry_api.SpanKind.CLIENT,
|
|
163
|
+
attributes: buildRequestAttributes(ctx)
|
|
164
|
+
}, parentContext, spanCallback);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Build request attributes for a GenAI span.
|
|
168
|
+
*/
|
|
169
|
+
function buildRequestAttributes(ctx) {
|
|
170
|
+
const attrs = {
|
|
171
|
+
[GenAIAttributes.SYSTEM]: ctx.system,
|
|
172
|
+
[GenAIAttributes.OPERATION_NAME]: ctx.operationName,
|
|
173
|
+
[GenAIAttributes.REQUEST_MODEL]: ctx.model,
|
|
174
|
+
[PromptfooAttributes.PROVIDER_ID]: ctx.providerId
|
|
175
|
+
};
|
|
176
|
+
if (ctx.maxTokens !== void 0) attrs[GenAIAttributes.REQUEST_MAX_TOKENS] = ctx.maxTokens;
|
|
177
|
+
if (ctx.temperature !== void 0) attrs[GenAIAttributes.REQUEST_TEMPERATURE] = ctx.temperature;
|
|
178
|
+
if (ctx.topP !== void 0) attrs[GenAIAttributes.REQUEST_TOP_P] = ctx.topP;
|
|
179
|
+
if (ctx.topK !== void 0) attrs[GenAIAttributes.REQUEST_TOP_K] = ctx.topK;
|
|
180
|
+
if (ctx.stopSequences && ctx.stopSequences.length > 0) attrs[GenAIAttributes.REQUEST_STOP_SEQUENCES] = ctx.stopSequences;
|
|
181
|
+
if (ctx.frequencyPenalty !== void 0) attrs[GenAIAttributes.REQUEST_FREQUENCY_PENALTY] = ctx.frequencyPenalty;
|
|
182
|
+
if (ctx.presencePenalty !== void 0) attrs[GenAIAttributes.REQUEST_PRESENCE_PENALTY] = ctx.presencePenalty;
|
|
183
|
+
if (ctx.evalId) attrs[PromptfooAttributes.EVAL_ID] = ctx.evalId;
|
|
184
|
+
if (ctx.testIndex !== void 0) attrs[PromptfooAttributes.TEST_INDEX] = ctx.testIndex;
|
|
185
|
+
if (ctx.promptLabel) attrs[PromptfooAttributes.PROMPT_LABEL] = ctx.promptLabel;
|
|
186
|
+
if (ctx.requestBody) attrs[PromptfooAttributes.REQUEST_BODY] = truncateBody(ctx.requestBody, ctx.sanitizeBodies);
|
|
187
|
+
return attrs;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Sanitize sensitive data from a body string.
|
|
191
|
+
* Redacts API keys, secrets, tokens, and other sensitive patterns.
|
|
192
|
+
*/
|
|
193
|
+
function sanitizeBody(body) {
|
|
194
|
+
let sanitized = body;
|
|
195
|
+
for (const { pattern, replacement } of SENSITIVE_PATTERNS) if (typeof replacement === "function") sanitized = sanitized.replace(pattern, replacement);
|
|
196
|
+
else sanitized = sanitized.replace(pattern, replacement);
|
|
197
|
+
return sanitized;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Truncate a body string to MAX_BODY_LENGTH.
|
|
201
|
+
* Optionally sanitizes sensitive data first if sanitize=true.
|
|
202
|
+
*
|
|
203
|
+
* @param body - The body string to process
|
|
204
|
+
* @param sanitize - Whether to sanitize sensitive data (defaults to true)
|
|
205
|
+
*/
|
|
206
|
+
function truncateBody(body, sanitize = true) {
|
|
207
|
+
const processed = sanitize ? sanitizeBody(body) : body;
|
|
208
|
+
if (processed.length <= MAX_BODY_LENGTH) return processed;
|
|
209
|
+
return processed.slice(0, MAX_BODY_LENGTH - 15) + "... [truncated]";
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Set response attributes on a span after the API call completes.
|
|
213
|
+
*
|
|
214
|
+
* @param span - The span to update
|
|
215
|
+
* @param result - The result data containing token usage and response metadata
|
|
216
|
+
* @param sanitize - Whether to sanitize sensitive data from response body (defaults to true)
|
|
217
|
+
*/
|
|
218
|
+
function setGenAIResponseAttributes(span, result, sanitize = true) {
|
|
219
|
+
if (result.tokenUsage) {
|
|
220
|
+
const usage = result.tokenUsage;
|
|
221
|
+
if (usage.prompt !== void 0) span.setAttribute(GenAIAttributes.USAGE_INPUT_TOKENS, usage.prompt);
|
|
222
|
+
if (usage.completion !== void 0) span.setAttribute(GenAIAttributes.USAGE_OUTPUT_TOKENS, usage.completion);
|
|
223
|
+
if (usage.total !== void 0) span.setAttribute(GenAIAttributes.USAGE_TOTAL_TOKENS, usage.total);
|
|
224
|
+
if (usage.cached !== void 0) span.setAttribute(GenAIAttributes.USAGE_CACHED_TOKENS, usage.cached);
|
|
225
|
+
if (usage.completionDetails) {
|
|
226
|
+
if (usage.completionDetails.reasoning !== void 0) span.setAttribute(GenAIAttributes.USAGE_REASONING_TOKENS, usage.completionDetails.reasoning);
|
|
227
|
+
if (usage.completionDetails.acceptedPrediction !== void 0) span.setAttribute(GenAIAttributes.USAGE_ACCEPTED_PREDICTION_TOKENS, usage.completionDetails.acceptedPrediction);
|
|
228
|
+
if (usage.completionDetails.rejectedPrediction !== void 0) span.setAttribute(GenAIAttributes.USAGE_REJECTED_PREDICTION_TOKENS, usage.completionDetails.rejectedPrediction);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (result.responseModel) span.setAttribute(GenAIAttributes.RESPONSE_MODEL, result.responseModel);
|
|
232
|
+
if (result.responseId) span.setAttribute(GenAIAttributes.RESPONSE_ID, result.responseId);
|
|
233
|
+
if (result.finishReasons && result.finishReasons.length > 0) span.setAttribute(GenAIAttributes.RESPONSE_FINISH_REASONS, result.finishReasons);
|
|
234
|
+
if (result.cacheHit !== void 0) span.setAttribute(PromptfooAttributes.CACHE_HIT, result.cacheHit);
|
|
235
|
+
if (result.responseBody) span.setAttribute(PromptfooAttributes.RESPONSE_BODY, truncateBody(result.responseBody, sanitize));
|
|
236
|
+
if (result.additionalAttributes) {
|
|
237
|
+
for (const [key, value] of Object.entries(result.additionalAttributes)) if (value !== void 0 && value !== null) if (typeof value === "string") span.setAttribute(key, truncateBody(value, sanitize));
|
|
238
|
+
else span.setAttribute(key, value);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Get the W3C traceparent header value from the current active span.
|
|
243
|
+
* Returns undefined if there is no active span.
|
|
244
|
+
*
|
|
245
|
+
* This can be used to propagate trace context to downstream services.
|
|
246
|
+
*/
|
|
247
|
+
function getTraceparent() {
|
|
248
|
+
const activeSpan = _opentelemetry_api.trace.getActiveSpan();
|
|
249
|
+
if (!activeSpan) return;
|
|
250
|
+
const ctx = activeSpan.spanContext();
|
|
251
|
+
const traceFlags = ctx.traceFlags.toString(16).padStart(2, "0");
|
|
252
|
+
return `00-${ctx.traceId}-${ctx.spanId}-${traceFlags}`;
|
|
253
|
+
}
|
|
254
|
+
//#endregion
|
|
255
|
+
Object.defineProperty(exports, "getTraceparent", {
|
|
256
|
+
enumerable: true,
|
|
257
|
+
get: function() {
|
|
258
|
+
return getTraceparent;
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
Object.defineProperty(exports, "withGenAISpan", {
|
|
262
|
+
enumerable: true,
|
|
263
|
+
get: function() {
|
|
264
|
+
return withGenAISpan;
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
//# sourceMappingURL=genaiTracer-CyZrmaK0.cjs.map
|