@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,122 @@
|
|
|
1
|
+
import { r as logger } from "./logger-C40ZGil9.js";
|
|
2
|
+
import { h as REQUEST_TIMEOUT_MS } from "./fetch-DQckpUFz.js";
|
|
3
|
+
import { r as fetchWithCache } from "./cache-BkrqU5Ba.js";
|
|
4
|
+
import { t as OpenAiGenericProvider } from "./openai-DumO8WQn.js";
|
|
5
|
+
import { i as OPENAI_TRANSCRIPTION_MODELS } from "./util-DsS_-v4p.js";
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
import path from "path";
|
|
8
|
+
//#region src/providers/openai/transcription.ts
|
|
9
|
+
var OpenAiTranscriptionProvider = class OpenAiTranscriptionProvider extends OpenAiGenericProvider {
|
|
10
|
+
static OPENAI_TRANSCRIPTION_MODEL_NAMES = OPENAI_TRANSCRIPTION_MODELS.map((model) => model.id);
|
|
11
|
+
config;
|
|
12
|
+
constructor(modelName, options = {}) {
|
|
13
|
+
if (!OpenAiTranscriptionProvider.OPENAI_TRANSCRIPTION_MODEL_NAMES.includes(modelName)) logger.debug(`Using unknown transcription model: ${modelName}`);
|
|
14
|
+
super(modelName, options);
|
|
15
|
+
this.config = options.config || {};
|
|
16
|
+
}
|
|
17
|
+
id() {
|
|
18
|
+
return `openai:transcription:${this.modelName}`;
|
|
19
|
+
}
|
|
20
|
+
toString() {
|
|
21
|
+
return `[OpenAI Transcription Provider ${this.modelName}]`;
|
|
22
|
+
}
|
|
23
|
+
calculateTranscriptionCost(durationSeconds) {
|
|
24
|
+
const model = OPENAI_TRANSCRIPTION_MODELS.find((m) => m.id === this.modelName);
|
|
25
|
+
if (!model || !model.cost) return 0;
|
|
26
|
+
return durationSeconds / 60 * model.cost.perMinute;
|
|
27
|
+
}
|
|
28
|
+
async callApi(prompt, context, _callApiOptions) {
|
|
29
|
+
if (!this.getApiKey()) throw new Error(this.getMissingApiKeyErrorMessage());
|
|
30
|
+
const config = {
|
|
31
|
+
...this.config,
|
|
32
|
+
...context?.prompt?.config
|
|
33
|
+
};
|
|
34
|
+
const audioFilePath = prompt.trim();
|
|
35
|
+
if (!fs.existsSync(audioFilePath)) return { error: `Audio file not found: ${audioFilePath}` };
|
|
36
|
+
try {
|
|
37
|
+
const fileBuffer = fs.readFileSync(audioFilePath);
|
|
38
|
+
const fileName = path.basename(audioFilePath);
|
|
39
|
+
const file = new File([fileBuffer], fileName);
|
|
40
|
+
const formData = new FormData();
|
|
41
|
+
formData.append("file", file);
|
|
42
|
+
formData.append("model", this.modelName);
|
|
43
|
+
if (config.language) formData.append("language", config.language);
|
|
44
|
+
if (config.prompt) formData.append("prompt", config.prompt);
|
|
45
|
+
if (config.temperature !== void 0) formData.append("temperature", config.temperature.toString());
|
|
46
|
+
if (config.timestamp_granularities && config.timestamp_granularities.length > 0) formData.append("timestamp_granularities", JSON.stringify(config.timestamp_granularities));
|
|
47
|
+
if (this.modelName.includes("diarize")) {
|
|
48
|
+
formData.append("response_format", "diarized_json");
|
|
49
|
+
if (config.num_speakers !== void 0) formData.append("num_speakers", config.num_speakers.toString());
|
|
50
|
+
if (config.speaker_labels && config.speaker_labels.length > 0) formData.append("speaker_labels", JSON.stringify(config.speaker_labels));
|
|
51
|
+
} else {
|
|
52
|
+
const responseFormat = this.modelName.startsWith("gpt-4o-") ? "json" : "verbose_json";
|
|
53
|
+
formData.append("response_format", responseFormat);
|
|
54
|
+
}
|
|
55
|
+
const headers = {
|
|
56
|
+
Authorization: `Bearer ${this.getApiKey()}`,
|
|
57
|
+
...this.getOrganization() ? { "OpenAI-Organization": this.getOrganization() } : {}
|
|
58
|
+
};
|
|
59
|
+
let data, status, statusText;
|
|
60
|
+
let cached = false;
|
|
61
|
+
try {
|
|
62
|
+
({data, cached, status, statusText} = await fetchWithCache(`${this.getApiUrl()}/audio/transcriptions`, {
|
|
63
|
+
method: "POST",
|
|
64
|
+
headers,
|
|
65
|
+
body: formData
|
|
66
|
+
}, REQUEST_TIMEOUT_MS, "json", context?.bustCache ?? context?.debug));
|
|
67
|
+
if (status < 200 || status >= 300) return { error: `API error: ${status} ${statusText}\n${typeof data === "string" ? data : JSON.stringify(data)}` };
|
|
68
|
+
} catch (err) {
|
|
69
|
+
logger.error("API call error", { error: err });
|
|
70
|
+
return { error: `API call error: ${String(err)}` };
|
|
71
|
+
}
|
|
72
|
+
if (data.error) return { error: typeof data.error === "string" ? data.error : JSON.stringify(data.error) };
|
|
73
|
+
const durationSeconds = data.duration || 0;
|
|
74
|
+
const cost = cached ? 0 : this.calculateTranscriptionCost(durationSeconds);
|
|
75
|
+
const segments = data.segments || [];
|
|
76
|
+
let avgLogprob;
|
|
77
|
+
let avgCompressionRatio;
|
|
78
|
+
let avgNoSpeechProb;
|
|
79
|
+
if (segments.length > 0) {
|
|
80
|
+
const validSegments = segments.filter((s) => s.avg_logprob !== void 0 || s.compression_ratio !== void 0 || s.no_speech_prob !== void 0);
|
|
81
|
+
if (validSegments.length > 0) {
|
|
82
|
+
const sumLogprob = validSegments.reduce((sum, s) => sum + (s.avg_logprob || 0), 0);
|
|
83
|
+
const sumCompressionRatio = validSegments.reduce((sum, s) => sum + (s.compression_ratio || 0), 0);
|
|
84
|
+
const sumNoSpeechProb = validSegments.reduce((sum, s) => sum + (s.no_speech_prob || 0), 0);
|
|
85
|
+
avgLogprob = validSegments.some((s) => s.avg_logprob !== void 0) ? sumLogprob / validSegments.length : void 0;
|
|
86
|
+
avgCompressionRatio = validSegments.some((s) => s.compression_ratio !== void 0) ? sumCompressionRatio / validSegments.length : void 0;
|
|
87
|
+
avgNoSpeechProb = validSegments.some((s) => s.no_speech_prob !== void 0) ? sumNoSpeechProb / validSegments.length : void 0;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
let output;
|
|
91
|
+
if (this.modelName.includes("diarize") && data.segments) output = data.segments.map((segment) => {
|
|
92
|
+
const speaker = segment.speaker || "Unknown";
|
|
93
|
+
const text = segment.text || "";
|
|
94
|
+
return `[${segment.start?.toFixed(2) || "0.00"}s - ${segment.end?.toFixed(2) || "0.00"}s] ${speaker}: ${text}`;
|
|
95
|
+
}).join("\n");
|
|
96
|
+
else if (data.text) output = data.text;
|
|
97
|
+
else return { error: "No transcription returned from API" };
|
|
98
|
+
return {
|
|
99
|
+
output,
|
|
100
|
+
cached,
|
|
101
|
+
cost,
|
|
102
|
+
metadata: {
|
|
103
|
+
task: data.task,
|
|
104
|
+
duration: durationSeconds,
|
|
105
|
+
language: data.language,
|
|
106
|
+
segments: data.segments?.length || 0,
|
|
107
|
+
...avgLogprob === void 0 ? {} : { avgLogprob },
|
|
108
|
+
...avgCompressionRatio === void 0 ? {} : { avgCompressionRatio },
|
|
109
|
+
...avgNoSpeechProb === void 0 ? {} : { avgNoSpeechProb },
|
|
110
|
+
...this.modelName.includes("diarize") && data.speakers ? { speakers: data.speakers } : {}
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
} catch (err) {
|
|
114
|
+
logger.error("Transcription error", { error: err });
|
|
115
|
+
return { error: `Transcription error: ${String(err)}` };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
//#endregion
|
|
120
|
+
export { OpenAiTranscriptionProvider };
|
|
121
|
+
|
|
122
|
+
//# sourceMappingURL=transcription-Cl_W16Pr.js.map
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
const require_logger = require("./logger-DyfK9PBt.cjs");
|
|
2
|
+
const require_fetch = require("./fetch-BTxakTSg.cjs");
|
|
3
|
+
const require_cache = require("./cache-DsCxFlsZ.cjs");
|
|
4
|
+
const require_openai = require("./openai-BWrJK9d8.cjs");
|
|
5
|
+
const require_util = require("./util-aWjdCYMI.cjs");
|
|
6
|
+
let fs = require("fs");
|
|
7
|
+
fs = require_logger.__toESM(fs);
|
|
8
|
+
let path = require("path");
|
|
9
|
+
path = require_logger.__toESM(path);
|
|
10
|
+
//#region src/providers/openai/transcription.ts
|
|
11
|
+
var OpenAiTranscriptionProvider = class OpenAiTranscriptionProvider extends require_openai.OpenAiGenericProvider {
|
|
12
|
+
static OPENAI_TRANSCRIPTION_MODEL_NAMES = require_util.OPENAI_TRANSCRIPTION_MODELS.map((model) => model.id);
|
|
13
|
+
config;
|
|
14
|
+
constructor(modelName, options = {}) {
|
|
15
|
+
if (!OpenAiTranscriptionProvider.OPENAI_TRANSCRIPTION_MODEL_NAMES.includes(modelName)) require_logger.logger.debug(`Using unknown transcription model: ${modelName}`);
|
|
16
|
+
super(modelName, options);
|
|
17
|
+
this.config = options.config || {};
|
|
18
|
+
}
|
|
19
|
+
id() {
|
|
20
|
+
return `openai:transcription:${this.modelName}`;
|
|
21
|
+
}
|
|
22
|
+
toString() {
|
|
23
|
+
return `[OpenAI Transcription Provider ${this.modelName}]`;
|
|
24
|
+
}
|
|
25
|
+
calculateTranscriptionCost(durationSeconds) {
|
|
26
|
+
const model = require_util.OPENAI_TRANSCRIPTION_MODELS.find((m) => m.id === this.modelName);
|
|
27
|
+
if (!model || !model.cost) return 0;
|
|
28
|
+
return durationSeconds / 60 * model.cost.perMinute;
|
|
29
|
+
}
|
|
30
|
+
async callApi(prompt, context, _callApiOptions) {
|
|
31
|
+
if (!this.getApiKey()) throw new Error(this.getMissingApiKeyErrorMessage());
|
|
32
|
+
const config = {
|
|
33
|
+
...this.config,
|
|
34
|
+
...context?.prompt?.config
|
|
35
|
+
};
|
|
36
|
+
const audioFilePath = prompt.trim();
|
|
37
|
+
if (!fs.default.existsSync(audioFilePath)) return { error: `Audio file not found: ${audioFilePath}` };
|
|
38
|
+
try {
|
|
39
|
+
const fileBuffer = fs.default.readFileSync(audioFilePath);
|
|
40
|
+
const fileName = path.default.basename(audioFilePath);
|
|
41
|
+
const file = new File([fileBuffer], fileName);
|
|
42
|
+
const formData = new FormData();
|
|
43
|
+
formData.append("file", file);
|
|
44
|
+
formData.append("model", this.modelName);
|
|
45
|
+
if (config.language) formData.append("language", config.language);
|
|
46
|
+
if (config.prompt) formData.append("prompt", config.prompt);
|
|
47
|
+
if (config.temperature !== void 0) formData.append("temperature", config.temperature.toString());
|
|
48
|
+
if (config.timestamp_granularities && config.timestamp_granularities.length > 0) formData.append("timestamp_granularities", JSON.stringify(config.timestamp_granularities));
|
|
49
|
+
if (this.modelName.includes("diarize")) {
|
|
50
|
+
formData.append("response_format", "diarized_json");
|
|
51
|
+
if (config.num_speakers !== void 0) formData.append("num_speakers", config.num_speakers.toString());
|
|
52
|
+
if (config.speaker_labels && config.speaker_labels.length > 0) formData.append("speaker_labels", JSON.stringify(config.speaker_labels));
|
|
53
|
+
} else {
|
|
54
|
+
const responseFormat = this.modelName.startsWith("gpt-4o-") ? "json" : "verbose_json";
|
|
55
|
+
formData.append("response_format", responseFormat);
|
|
56
|
+
}
|
|
57
|
+
const headers = {
|
|
58
|
+
Authorization: `Bearer ${this.getApiKey()}`,
|
|
59
|
+
...this.getOrganization() ? { "OpenAI-Organization": this.getOrganization() } : {}
|
|
60
|
+
};
|
|
61
|
+
let data, status, statusText;
|
|
62
|
+
let cached = false;
|
|
63
|
+
try {
|
|
64
|
+
({data, cached, status, statusText} = await require_cache.fetchWithCache(`${this.getApiUrl()}/audio/transcriptions`, {
|
|
65
|
+
method: "POST",
|
|
66
|
+
headers,
|
|
67
|
+
body: formData
|
|
68
|
+
}, require_fetch.REQUEST_TIMEOUT_MS, "json", context?.bustCache ?? context?.debug));
|
|
69
|
+
if (status < 200 || status >= 300) return { error: `API error: ${status} ${statusText}\n${typeof data === "string" ? data : JSON.stringify(data)}` };
|
|
70
|
+
} catch (err) {
|
|
71
|
+
require_logger.logger.error("API call error", { error: err });
|
|
72
|
+
return { error: `API call error: ${String(err)}` };
|
|
73
|
+
}
|
|
74
|
+
if (data.error) return { error: typeof data.error === "string" ? data.error : JSON.stringify(data.error) };
|
|
75
|
+
const durationSeconds = data.duration || 0;
|
|
76
|
+
const cost = cached ? 0 : this.calculateTranscriptionCost(durationSeconds);
|
|
77
|
+
const segments = data.segments || [];
|
|
78
|
+
let avgLogprob;
|
|
79
|
+
let avgCompressionRatio;
|
|
80
|
+
let avgNoSpeechProb;
|
|
81
|
+
if (segments.length > 0) {
|
|
82
|
+
const validSegments = segments.filter((s) => s.avg_logprob !== void 0 || s.compression_ratio !== void 0 || s.no_speech_prob !== void 0);
|
|
83
|
+
if (validSegments.length > 0) {
|
|
84
|
+
const sumLogprob = validSegments.reduce((sum, s) => sum + (s.avg_logprob || 0), 0);
|
|
85
|
+
const sumCompressionRatio = validSegments.reduce((sum, s) => sum + (s.compression_ratio || 0), 0);
|
|
86
|
+
const sumNoSpeechProb = validSegments.reduce((sum, s) => sum + (s.no_speech_prob || 0), 0);
|
|
87
|
+
avgLogprob = validSegments.some((s) => s.avg_logprob !== void 0) ? sumLogprob / validSegments.length : void 0;
|
|
88
|
+
avgCompressionRatio = validSegments.some((s) => s.compression_ratio !== void 0) ? sumCompressionRatio / validSegments.length : void 0;
|
|
89
|
+
avgNoSpeechProb = validSegments.some((s) => s.no_speech_prob !== void 0) ? sumNoSpeechProb / validSegments.length : void 0;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
let output;
|
|
93
|
+
if (this.modelName.includes("diarize") && data.segments) output = data.segments.map((segment) => {
|
|
94
|
+
const speaker = segment.speaker || "Unknown";
|
|
95
|
+
const text = segment.text || "";
|
|
96
|
+
return `[${segment.start?.toFixed(2) || "0.00"}s - ${segment.end?.toFixed(2) || "0.00"}s] ${speaker}: ${text}`;
|
|
97
|
+
}).join("\n");
|
|
98
|
+
else if (data.text) output = data.text;
|
|
99
|
+
else return { error: "No transcription returned from API" };
|
|
100
|
+
return {
|
|
101
|
+
output,
|
|
102
|
+
cached,
|
|
103
|
+
cost,
|
|
104
|
+
metadata: {
|
|
105
|
+
task: data.task,
|
|
106
|
+
duration: durationSeconds,
|
|
107
|
+
language: data.language,
|
|
108
|
+
segments: data.segments?.length || 0,
|
|
109
|
+
...avgLogprob === void 0 ? {} : { avgLogprob },
|
|
110
|
+
...avgCompressionRatio === void 0 ? {} : { avgCompressionRatio },
|
|
111
|
+
...avgNoSpeechProb === void 0 ? {} : { avgNoSpeechProb },
|
|
112
|
+
...this.modelName.includes("diarize") && data.speakers ? { speakers: data.speakers } : {}
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
} catch (err) {
|
|
116
|
+
require_logger.logger.error("Transcription error", { error: err });
|
|
117
|
+
return { error: `Transcription error: ${String(err)}` };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
//#endregion
|
|
122
|
+
exports.OpenAiTranscriptionProvider = OpenAiTranscriptionProvider;
|
|
123
|
+
|
|
124
|
+
//# sourceMappingURL=transcription-yt1EecY8.cjs.map
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
const require_logger = require("./logger-DyfK9PBt.cjs");
|
|
2
|
+
const require_esm = require("./esm-C62Zofr1.cjs");
|
|
3
|
+
const require_pythonUtils = require("./pythonUtils-BD0druiM.cjs");
|
|
4
|
+
const require_fileExtensions = require("./fileExtensions-bYh77CN8.cjs");
|
|
5
|
+
//#region src/util/processShim.ts
|
|
6
|
+
/**
|
|
7
|
+
* Browser-safe process shim module.
|
|
8
|
+
*
|
|
9
|
+
* This module provides a shimmed process object that works in both Node.js and browser
|
|
10
|
+
* environments. In Node.js, it provides full functionality including process.mainModule.require.
|
|
11
|
+
* In browsers, it returns a minimal shim that throws helpful errors when Node.js-specific
|
|
12
|
+
* features are accessed.
|
|
13
|
+
*
|
|
14
|
+
* This separation is necessary because:
|
|
15
|
+
* 1. The promptfoo webui imports httpTransforms.ts which needs getProcessShim()
|
|
16
|
+
* 2. httpTransforms.ts is designed to be frontend-importable for testing transforms in the UI
|
|
17
|
+
* 3. The Node.js implementation uses createRequire from 'node:module' which doesn't exist in browsers
|
|
18
|
+
*
|
|
19
|
+
* By using runtime environment detection and dynamic imports, we can:
|
|
20
|
+
* - Avoid top-level imports of Node.js-only modules that would break browser bundling
|
|
21
|
+
* - Provide appropriate functionality for each environment
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Detects if the current environment is a browser or web worker.
|
|
25
|
+
* Handles test environments (jsdom/happy-dom) that define window in Node.js.
|
|
26
|
+
*/
|
|
27
|
+
function isBrowserEnvironment() {
|
|
28
|
+
if (typeof process !== "undefined" && typeof process.versions?.node === "string") return false;
|
|
29
|
+
return typeof window !== "undefined" || typeof self !== "undefined" && typeof self.importScripts === "function";
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Creates a minimal process shim for browser environments.
|
|
33
|
+
* This shim provides helpful error messages when Node.js-specific features are accessed.
|
|
34
|
+
*/
|
|
35
|
+
function createBrowserProcessShim() {
|
|
36
|
+
return {
|
|
37
|
+
env: {},
|
|
38
|
+
mainModule: {
|
|
39
|
+
require: () => {
|
|
40
|
+
throw new Error("require() is not available in browser transforms. Use standard JavaScript instead.");
|
|
41
|
+
},
|
|
42
|
+
exports: {},
|
|
43
|
+
id: ".",
|
|
44
|
+
filename: "",
|
|
45
|
+
loaded: true,
|
|
46
|
+
children: [],
|
|
47
|
+
paths: []
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
let cachedNodeProcessShim = null;
|
|
52
|
+
/**
|
|
53
|
+
* Returns a shimmed process object that works in both Node.js and browser environments.
|
|
54
|
+
*
|
|
55
|
+
* In Node.js:
|
|
56
|
+
* - Returns a proxy with process.mainModule.require shimmed for ESM compatibility
|
|
57
|
+
* - Allows inline transforms to use require() even in ESM context
|
|
58
|
+
*
|
|
59
|
+
* In browsers:
|
|
60
|
+
* - Returns a minimal shim with helpful error messages
|
|
61
|
+
* - Allows simple transforms that don't use require() to work
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* // In Node.js - can use require
|
|
65
|
+
* const fn = new Function('data', 'process', `return process.mainModule.require('fs')`);
|
|
66
|
+
* fn(data, getProcessShim());
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* // In browser - simple transforms work
|
|
70
|
+
* const fn = new Function('data', 'process', `return data.toUpperCase()`);
|
|
71
|
+
* fn(data, getProcessShim());
|
|
72
|
+
*/
|
|
73
|
+
function getProcessShim() {
|
|
74
|
+
if (isBrowserEnvironment()) return createBrowserProcessShim();
|
|
75
|
+
if (!cachedNodeProcessShim) try {
|
|
76
|
+
const esmRequire = require("node:module").createRequire(require("url").pathToFileURL(__filename).href);
|
|
77
|
+
cachedNodeProcessShim = new Proxy(process, { get(target, prop) {
|
|
78
|
+
if (prop === "mainModule") return {
|
|
79
|
+
require: esmRequire,
|
|
80
|
+
exports: {},
|
|
81
|
+
id: ".",
|
|
82
|
+
filename: "",
|
|
83
|
+
loaded: true,
|
|
84
|
+
children: [],
|
|
85
|
+
paths: []
|
|
86
|
+
};
|
|
87
|
+
return Reflect.get(target, prop);
|
|
88
|
+
} });
|
|
89
|
+
} catch {
|
|
90
|
+
return createBrowserProcessShim();
|
|
91
|
+
}
|
|
92
|
+
return cachedNodeProcessShim;
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/util/transform.ts
|
|
96
|
+
const TransformInputType = {
|
|
97
|
+
OUTPUT: "output",
|
|
98
|
+
VARS: "vars"
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Parses a file path string to extract the file path and function name.
|
|
102
|
+
* Handles Windows drive letters (e.g., C:\path\to\file.js:functionName).
|
|
103
|
+
* @param filePath - The file path string, potentially including a function name.
|
|
104
|
+
* @returns A tuple containing the file path and function name (if present).
|
|
105
|
+
*/
|
|
106
|
+
function parseFilePathAndFunctionName(filePath) {
|
|
107
|
+
const lastColonIndex = filePath.lastIndexOf(":");
|
|
108
|
+
if (lastColonIndex > 1) return [filePath.slice(0, lastColonIndex), filePath.slice(lastColonIndex + 1)];
|
|
109
|
+
return [filePath, void 0];
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Retrieves a JavaScript transform function from a file.
|
|
113
|
+
* @param filePath - The path to the JavaScript file.
|
|
114
|
+
* @param functionName - Optional name of the function to retrieve.
|
|
115
|
+
* @returns A Promise resolving to the requested function.
|
|
116
|
+
* @throws Error if the file doesn't export a valid function.
|
|
117
|
+
*/
|
|
118
|
+
async function getJavascriptTransformFunction(filePath, functionName) {
|
|
119
|
+
const requiredModule = await require_esm.importModule(filePath);
|
|
120
|
+
if (functionName && Object.prototype.hasOwnProperty.call(requiredModule, functionName) && typeof requiredModule[functionName] === "function") return requiredModule[functionName];
|
|
121
|
+
else if (typeof requiredModule === "function") return requiredModule;
|
|
122
|
+
else if (requiredModule.default && typeof requiredModule.default === "function") return requiredModule.default;
|
|
123
|
+
throw new Error(`Transform ${filePath} must export a function, have a default export as a function, or export the specified function "${functionName}"`);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Creates a function that runs a Python transform function.
|
|
127
|
+
* @param filePath - The path to the Python file.
|
|
128
|
+
* @param functionName - The name of the function to run (defaults to 'get_transform').
|
|
129
|
+
* @returns A function that executes the Python transform.
|
|
130
|
+
*/
|
|
131
|
+
function getPythonTransformFunction(filePath, functionName = "get_transform") {
|
|
132
|
+
return async (output, context) => {
|
|
133
|
+
return require_pythonUtils.runPython(filePath, functionName, [output, context]);
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Retrieves a transform function from a file, supporting both JavaScript and Python.
|
|
138
|
+
* @param filePath - The path to the file, including the 'file://' prefix.
|
|
139
|
+
* @returns A Promise resolving to the requested function.
|
|
140
|
+
* @throws Error if the file format is unsupported.
|
|
141
|
+
*/
|
|
142
|
+
async function getFileTransformFunction(filePath) {
|
|
143
|
+
const [actualFilePath, functionName] = parseFilePathAndFunctionName(filePath.slice(7));
|
|
144
|
+
const fullPath = require_esm.safeJoin(require_logger.state.basePath || "", actualFilePath);
|
|
145
|
+
if (require_fileExtensions.isJavascriptFile(fullPath)) return getJavascriptTransformFunction(fullPath, functionName);
|
|
146
|
+
else if (fullPath.endsWith(".py")) return getPythonTransformFunction(fullPath, functionName);
|
|
147
|
+
throw new Error(`Unsupported transform file format: file://${actualFilePath}`);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Creates a function from inline JavaScript code.
|
|
151
|
+
* @param code - The JavaScript code to convert into a function.
|
|
152
|
+
* @returns A Function created from the provided code.
|
|
153
|
+
*
|
|
154
|
+
* The function receives three parameters:
|
|
155
|
+
* - The input (output or vars depending on inputType)
|
|
156
|
+
* - A context object
|
|
157
|
+
* - A process object with mainModule.require shimmed for backwards compatibility
|
|
158
|
+
*
|
|
159
|
+
* To use require in inline transforms, use: process.mainModule.require('module-name')
|
|
160
|
+
* Or assign it to a variable: const require = process.mainModule.require;
|
|
161
|
+
*/
|
|
162
|
+
function getInlineTransformFunction(code, inputType) {
|
|
163
|
+
return new Function(inputType, "context", "process", code.includes("\n") ? code : `return ${code}`);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Determines and retrieves the appropriate transform function based on the input.
|
|
167
|
+
* @param codeOrFilepath - Either inline code or a file path starting with 'file://'.
|
|
168
|
+
* @returns A Promise resolving to the appropriate transform function.
|
|
169
|
+
*/
|
|
170
|
+
async function getTransformFunction(codeOrFilepath, inputType) {
|
|
171
|
+
let transformFn = null;
|
|
172
|
+
if (codeOrFilepath.startsWith("file://")) try {
|
|
173
|
+
transformFn = await getFileTransformFunction(codeOrFilepath);
|
|
174
|
+
} catch (error) {
|
|
175
|
+
require_logger.logger.error(`Error loading transform function from file: ${error instanceof Error ? error.message : String(error)}`);
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
else try {
|
|
179
|
+
transformFn = getInlineTransformFunction(codeOrFilepath, inputType);
|
|
180
|
+
} catch (error) {
|
|
181
|
+
require_logger.logger.error(`Error creating inline transform function: ${error instanceof Error ? error.message : String(error)}`);
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
return transformFn;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Transforms the output using a specified function or file.
|
|
188
|
+
*
|
|
189
|
+
* @param codeOrFilepath - The transformation function code or file path.
|
|
190
|
+
* If it starts with 'file://', it's treated as a file path. The file path can
|
|
191
|
+
* optionally include a function name (e.g., 'file://transform.js:myFunction').
|
|
192
|
+
* If no function name is provided for Python files, it defaults to 'get_transform'.
|
|
193
|
+
* For inline code, it's treated as JavaScript.
|
|
194
|
+
* @param transformInput - The output to be transformed. Can be a string or an object.
|
|
195
|
+
* @param context - A context object that will be passed to the transform function.
|
|
196
|
+
* @param validateReturn - Optional. If true, throws an error if the transform function doesn't return a value.
|
|
197
|
+
* @returns A promise that resolves to the transformed output.
|
|
198
|
+
* @throws Error if the file format is unsupported or if the transform function
|
|
199
|
+
* doesn't return a value (unless validateReturn is false).
|
|
200
|
+
*/
|
|
201
|
+
async function transform(codeOrFilepath, transformInput, context, validateReturn = true, inputType = TransformInputType.OUTPUT) {
|
|
202
|
+
const postprocessFn = await getTransformFunction(codeOrFilepath, inputType);
|
|
203
|
+
if (!postprocessFn) throw new Error(`Invalid transform function for ${codeOrFilepath}`);
|
|
204
|
+
const ret = await Promise.resolve(postprocessFn(transformInput, context, getProcessShim()));
|
|
205
|
+
if (validateReturn && (ret === null || ret === void 0)) throw new Error(`Transform function did not return a value\n\n${codeOrFilepath}`);
|
|
206
|
+
return ret;
|
|
207
|
+
}
|
|
208
|
+
//#endregion
|
|
209
|
+
Object.defineProperty(exports, "TransformInputType", {
|
|
210
|
+
enumerable: true,
|
|
211
|
+
get: function() {
|
|
212
|
+
return TransformInputType;
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
Object.defineProperty(exports, "getProcessShim", {
|
|
216
|
+
enumerable: true,
|
|
217
|
+
get: function() {
|
|
218
|
+
return getProcessShim;
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
Object.defineProperty(exports, "transform", {
|
|
222
|
+
enumerable: true,
|
|
223
|
+
get: function() {
|
|
224
|
+
return transform;
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
//# sourceMappingURL=transform-BCtGrl_W.cjs.map
|