braintrust 3.31.0 → 3.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dev/dist/index.d.mts +736 -0
  2. package/dev/dist/index.d.ts +736 -0
  3. package/dev/dist/index.js +1280 -428
  4. package/dev/dist/index.mjs +859 -7
  5. package/dist/apply-auto-instrumentation.js +281 -216
  6. package/dist/apply-auto-instrumentation.mjs +66 -1
  7. package/dist/auto-instrumentations/bundler/esbuild.cjs +104 -2
  8. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  9. package/dist/auto-instrumentations/bundler/next.cjs +104 -2
  10. package/dist/auto-instrumentations/bundler/next.mjs +3 -3
  11. package/dist/auto-instrumentations/bundler/rollup.cjs +104 -2
  12. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  13. package/dist/auto-instrumentations/bundler/vite.cjs +104 -2
  14. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  15. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +104 -2
  16. package/dist/auto-instrumentations/bundler/webpack.cjs +104 -2
  17. package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
  18. package/dist/auto-instrumentations/{chunk-U64OYU4Q.mjs → chunk-AFND2U7E.mjs} +38 -1
  19. package/dist/auto-instrumentations/{chunk-OXINGIEZ.mjs → chunk-QEEPRBIS.mjs} +1 -1
  20. package/dist/auto-instrumentations/{chunk-LW4HDHXT.mjs → chunk-RI4Y55ZF.mjs} +69 -2
  21. package/dist/auto-instrumentations/hook.mjs +124 -3
  22. package/dist/auto-instrumentations/index.cjs +39 -1
  23. package/dist/auto-instrumentations/index.d.mts +3 -1
  24. package/dist/auto-instrumentations/index.d.ts +3 -1
  25. package/dist/auto-instrumentations/index.mjs +3 -1
  26. package/dist/browser.d.mts +2124 -2
  27. package/dist/browser.d.ts +2124 -2
  28. package/dist/browser.js +994 -10
  29. package/dist/browser.mjs +994 -10
  30. package/dist/{chunk-AJT4FR25.mjs → chunk-4QSAHP7D.mjs} +818 -5
  31. package/dist/{chunk-4AQGZS6X.js → chunk-AW4QECG5.js} +47 -4
  32. package/dist/{chunk-V32LW47Z.js → chunk-BTRLPQG5.js} +1663 -850
  33. package/dist/{chunk-CE3BLB2L.mjs → chunk-WV6QZI2W.mjs} +46 -3
  34. package/dist/cli.js +923 -8
  35. package/dist/edge-light.d.mts +1 -1
  36. package/dist/edge-light.d.ts +1 -1
  37. package/dist/edge-light.js +994 -10
  38. package/dist/edge-light.mjs +994 -10
  39. package/dist/index.d.mts +2124 -2
  40. package/dist/index.d.ts +2124 -2
  41. package/dist/index.js +581 -447
  42. package/dist/index.mjs +136 -2
  43. package/dist/instrumentation/index.d.mts +434 -0
  44. package/dist/instrumentation/index.d.ts +434 -0
  45. package/dist/instrumentation/index.js +859 -7
  46. package/dist/instrumentation/index.mjs +859 -7
  47. package/dist/vitest-evals-reporter.js +16 -16
  48. package/dist/vitest-evals-reporter.mjs +2 -2
  49. package/dist/workerd.d.mts +1 -1
  50. package/dist/workerd.d.ts +1 -1
  51. package/dist/workerd.js +994 -10
  52. package/dist/workerd.mjs +994 -10
  53. package/package.json +1 -1
  54. package/util/dist/index.d.mts +326 -0
  55. package/util/dist/index.d.ts +326 -0
@@ -12,6 +12,7 @@ import {
12
12
  cursorSDKChannels,
13
13
  debugLogger,
14
14
  detectSpanOriginEnvironment,
15
+ elevenLabsChannels,
15
16
  flueChannels,
16
17
  genkitChannels,
17
18
  genkitCoreChannels,
@@ -22,6 +23,7 @@ import {
22
23
  gitHubCopilotChannels,
23
24
  googleADKChannels,
24
25
  googleGenAIChannels,
26
+ googleGenerativeAIChannels,
25
27
  groqChannels,
26
28
  harnessAgentChannels,
27
29
  huggingFaceChannels,
@@ -52,7 +54,7 @@ import {
52
54
  strandsAgentSDKChannels,
53
55
  voyageAIChannels,
54
56
  withSpanInstrumentationName
55
- } from "./chunk-CE3BLB2L.mjs";
57
+ } from "./chunk-WV6QZI2W.mjs";
56
58
 
57
59
  // src/id-gen.ts
58
60
  import { v4 as uuidv4 } from "uuid";
@@ -2013,6 +2015,14 @@ var ChatCompletionContentPartImageWithTitle = z6.object({
2013
2015
  ttl: z6.enum(["5m", "1h"]).optional()
2014
2016
  }).optional()
2015
2017
  });
2018
+ var ChatCompletionContentPartInputAudioWithTitle = z6.object({
2019
+ input_audio: z6.object({ data: z6.string(), format: z6.enum(["wav", "mp3"]) }),
2020
+ type: z6.literal("input_audio"),
2021
+ cache_control: z6.object({
2022
+ type: z6.literal("ephemeral"),
2023
+ ttl: z6.enum(["5m", "1h"]).optional()
2024
+ }).optional()
2025
+ });
2016
2026
  var ChatCompletionContentPartFileFile = z6.object({ file_data: z6.string(), filename: z6.string(), file_id: z6.string() }).partial();
2017
2027
  var ChatCompletionContentPartFileWithTitle = z6.object({
2018
2028
  file: ChatCompletionContentPartFileFile,
@@ -2025,6 +2035,7 @@ var ChatCompletionContentPartFileWithTitle = z6.object({
2025
2035
  var ChatCompletionContentPart = z6.union([
2026
2036
  ChatCompletionContentPartTextWithTitle,
2027
2037
  ChatCompletionContentPartImageWithTitle,
2038
+ ChatCompletionContentPartInputAudioWithTitle,
2028
2039
  ChatCompletionContentPartFileWithTitle
2029
2040
  ]);
2030
2041
  var ChatCompletionContentPartText = z6.object({
@@ -10743,6 +10754,16 @@ function renderMessageImpl(render, message, variables) {
10743
10754
  }
10744
10755
  }
10745
10756
  ];
10757
+ case "input_audio":
10758
+ return [
10759
+ {
10760
+ ...c,
10761
+ input_audio: {
10762
+ ...c.input_audio,
10763
+ data: render(c.input_audio.data)
10764
+ }
10765
+ }
10766
+ ];
10746
10767
  case "file":
10747
10768
  return [
10748
10769
  {
@@ -24562,6 +24583,328 @@ var OpenAIAgentsPlugin = class extends BasePlugin {
24562
24583
  }
24563
24584
  };
24564
24585
 
24586
+ // src/instrumentation/plugins/google-generative-ai-plugin.ts
24587
+ var GENERATION_CONFIG_KEYS = [
24588
+ "temperature",
24589
+ "topP",
24590
+ "topK",
24591
+ "candidateCount",
24592
+ "maxOutputTokens",
24593
+ "stopSequences",
24594
+ "responseMimeType",
24595
+ "responseSchema",
24596
+ "presencePenalty",
24597
+ "frequencyPenalty",
24598
+ "responseLogprobs",
24599
+ "logprobs",
24600
+ "thinkingConfig"
24601
+ ];
24602
+ var GoogleGenerativeAIPlugin = class extends BasePlugin {
24603
+ onEnable() {
24604
+ this.unsubscribers.push(
24605
+ interceptCall(
24606
+ googleGenerativeAIChannels.generateContent,
24607
+ "generateContent"
24608
+ ),
24609
+ interceptCall(
24610
+ googleGenerativeAIChannels.generateContentStream,
24611
+ "generateContentStream"
24612
+ ),
24613
+ interceptCall(googleGenerativeAIChannels.sendMessage, "sendMessage"),
24614
+ interceptCall(
24615
+ googleGenerativeAIChannels.sendMessageStream,
24616
+ "sendMessageStream"
24617
+ ),
24618
+ interceptCall(googleGenerativeAIChannels.embedContent, "embedContent"),
24619
+ interceptCall(
24620
+ googleGenerativeAIChannels.batchEmbedContents,
24621
+ "batchEmbedContents"
24622
+ )
24623
+ );
24624
+ }
24625
+ onDisable() {
24626
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
24627
+ }
24628
+ };
24629
+ function interceptCall(channel, operation) {
24630
+ return channel.intercept((target, thisArg, args) => {
24631
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
24632
+ if (isAutoInstrumentationSuppressed()) return invokeTarget();
24633
+ const self = thisArg;
24634
+ const chat = operation.startsWith("sendMessage");
24635
+ const embedding = operation === "embedContent" || operation === "batchEmbedContents";
24636
+ const start = getCurrentUnixTimestamp();
24637
+ let span;
24638
+ try {
24639
+ span = startSpan(
24640
+ withSpanInstrumentationName(
24641
+ {
24642
+ name: embedding ? operation === "embedContent" ? "embed_content" : "batch_embed_contents" : "generate_content",
24643
+ spanAttributes: { type: "llm" /* LLM */ },
24644
+ event: extractInput(self, args[0], operation)
24645
+ },
24646
+ INSTRUMENTATION_NAMES.GOOGLE_GENERATIVE_AI
24647
+ )
24648
+ );
24649
+ } catch (error) {
24650
+ debugLogger.error("Error starting Google Generative AI span:", error);
24651
+ return invokeTarget();
24652
+ }
24653
+ let ended = false;
24654
+ const finish = (log2) => {
24655
+ if (ended) return;
24656
+ ended = true;
24657
+ try {
24658
+ log2();
24659
+ } catch (error) {
24660
+ debugLogger.error("Error logging Google Generative AI span:", error);
24661
+ }
24662
+ try {
24663
+ span.end();
24664
+ } catch (error) {
24665
+ debugLogger.error("Error ending Google Generative AI span:", error);
24666
+ }
24667
+ };
24668
+ if (chat) {
24669
+ try {
24670
+ void self._sendPromise.then(
24671
+ () => {
24672
+ try {
24673
+ span.log(extractInput(self, args[0], operation));
24674
+ } catch (error) {
24675
+ debugLogger.error("Error capturing Google chat history:", error);
24676
+ }
24677
+ },
24678
+ () => {
24679
+ }
24680
+ );
24681
+ } catch (error) {
24682
+ debugLogger.error("Error observing Google chat history:", error);
24683
+ }
24684
+ }
24685
+ let result;
24686
+ try {
24687
+ result = withCurrent(
24688
+ span,
24689
+ () => runWithAutoInstrumentationSuppressed(invokeTarget)
24690
+ );
24691
+ } catch (error) {
24692
+ finish(() => span.log({ error }));
24693
+ throw error;
24694
+ }
24695
+ void Promise.resolve(result).then(
24696
+ (value) => {
24697
+ try {
24698
+ if ("stream" in value) {
24699
+ let firstToken = false;
24700
+ const partial = { candidates: [] };
24701
+ const candidates = /* @__PURE__ */ new Map();
24702
+ patchStreamIfNeeded(value.stream, {
24703
+ aroundNext: (callback) => withCurrent(span, callback),
24704
+ onChunk: (chunk) => {
24705
+ for (const candidate of chunk.candidates ?? []) {
24706
+ const index = candidate.index ?? 0;
24707
+ const previous = candidates.get(index);
24708
+ const parts = [...previous?.content?.parts ?? []];
24709
+ for (const part of candidate.content?.parts ?? []) {
24710
+ const last = parts[parts.length - 1];
24711
+ if (part.text !== void 0 && last?.text !== void 0) {
24712
+ parts[parts.length - 1] = {
24713
+ ...last,
24714
+ text: last.text + part.text
24715
+ };
24716
+ } else parts.push(part);
24717
+ }
24718
+ candidates.set(index, {
24719
+ ...previous,
24720
+ ...candidate,
24721
+ content: {
24722
+ role: candidate.content?.role ?? previous?.content?.role ?? "model",
24723
+ parts
24724
+ }
24725
+ });
24726
+ }
24727
+ partial.candidates = Array.from(candidates.values());
24728
+ if (chunk.usageMetadata)
24729
+ partial.usageMetadata = chunk.usageMetadata;
24730
+ if (!firstToken && chunk.candidates?.some(
24731
+ (candidate) => candidate.content?.parts.some(
24732
+ (part) => part.text !== void 0 ? part.text.length > 0 : Object.keys(part).length > 0
24733
+ )
24734
+ )) {
24735
+ firstToken = true;
24736
+ span.log({
24737
+ metrics: {
24738
+ time_to_first_token: getCurrentUnixTimestamp() - start
24739
+ }
24740
+ });
24741
+ }
24742
+ },
24743
+ onComplete: () => {
24744
+ },
24745
+ onError: (error) => finish(() => {
24746
+ logResponse(span, partial);
24747
+ span.log({ error });
24748
+ }),
24749
+ onCancel: () => finish(() => logResponse(span, partial))
24750
+ });
24751
+ void value.response.then(
24752
+ (response) => finish(() => logResponse(span, response)),
24753
+ (error) => finish(() => {
24754
+ logResponse(span, partial);
24755
+ span.log({ error });
24756
+ })
24757
+ );
24758
+ } else if ("response" in value) {
24759
+ finish(() => logResponse(span, value.response));
24760
+ } else {
24761
+ const metrics = {};
24762
+ const promptTokens = value.usageMetadata?.promptTokenCount;
24763
+ if (typeof promptTokens === "number" && Number.isFinite(promptTokens) && promptTokens >= 0) {
24764
+ metrics.prompt_tokens = promptTokens;
24765
+ metrics.tokens = promptTokens;
24766
+ }
24767
+ for (const detail of value.usageMetadata?.promptTokenDetails ?? []) {
24768
+ if (detail.modality === "AUDIO" && typeof detail.tokenCount === "number" && Number.isFinite(detail.tokenCount) && detail.tokenCount >= 0) {
24769
+ metrics.prompt_audio_tokens = (metrics.prompt_audio_tokens ?? 0) + detail.tokenCount;
24770
+ }
24771
+ }
24772
+ finish(
24773
+ () => span.log({
24774
+ metrics,
24775
+ output: {
24776
+ count: value.embeddings?.length ?? (value.embedding ? 1 : 0)
24777
+ }
24778
+ })
24779
+ );
24780
+ }
24781
+ } catch (error) {
24782
+ debugLogger.error(
24783
+ "Error observing Google Generative AI result:",
24784
+ error
24785
+ );
24786
+ finish(() => {
24787
+ });
24788
+ }
24789
+ },
24790
+ (error) => finish(() => span.log({ error }))
24791
+ );
24792
+ return result;
24793
+ });
24794
+ }
24795
+ function normalizeContent(message) {
24796
+ const parts = (typeof message === "string" ? [message] : message).map(
24797
+ (part) => typeof part === "string" ? { text: part } : part
24798
+ );
24799
+ return {
24800
+ role: parts.some((part) => part.functionResponse) ? "function" : "user",
24801
+ parts
24802
+ };
24803
+ }
24804
+ function extractInput(self, request, operation) {
24805
+ const model = self.model.replace(/^models\//, "");
24806
+ if (operation === "embedContent" || operation === "batchEmbedContents") {
24807
+ const requests = operation === "batchEmbedContents" ? request.requests : [
24808
+ typeof request === "string" || Array.isArray(request) ? { content: normalizeContent(request) } : request
24809
+ ];
24810
+ const dimensions = requests[0]?.outputDimensionality;
24811
+ return {
24812
+ input: {
24813
+ inputs: convertAttachments(requests).map((item) => ({
24814
+ content: item.content.parts.length === 1 && item.content.parts[0].text !== void 0 ? item.content.parts[0].text : item.content.parts.map((part) => {
24815
+ if (part.text !== void 0)
24816
+ return { type: "text", text: part.text };
24817
+ const mimeType = part.inlineData?.mimeType ?? part.fileData?.mimeType;
24818
+ const data = part.inlineData ? typeof part.inlineData.data === "string" ? `data:${mimeType};base64,${part.inlineData.data}` : part.inlineData.data : part.fileData?.fileUri;
24819
+ return mimeType?.startsWith("image/") ? { type: "image_url", image_url: { url: data } } : { type: "file", file: { file_data: data } };
24820
+ })
24821
+ })),
24822
+ ...dimensions !== void 0 && requests.every((item) => item.outputDimensionality === dimensions) ? { output_dimensions: dimensions } : {}
24823
+ },
24824
+ metadata: { model, provider: "google" }
24825
+ };
24826
+ }
24827
+ const chat = operation.startsWith("sendMessage");
24828
+ const config = chat ? self.params ?? {} : self;
24829
+ const params = typeof request === "string" || Array.isArray(request) ? { contents: [normalizeContent(request)] } : request;
24830
+ const system = params.systemInstruction ?? config.systemInstruction;
24831
+ const systemContent = typeof system === "string" ? { role: "system", parts: [{ text: system }] } : system && "parts" in system ? { ...system, role: "system" } : system ? { role: "system", parts: [system] } : void 0;
24832
+ const contents = [
24833
+ ...systemContent ? [systemContent] : [],
24834
+ ...chat ? self._history : [],
24835
+ ...params.contents
24836
+ ];
24837
+ const metadata = { model, provider: "google" };
24838
+ const generation = params.generationConfig ?? config.generationConfig;
24839
+ for (const key of GENERATION_CONFIG_KEYS) {
24840
+ if (generation && Object.hasOwn(generation, key))
24841
+ metadata[key] = generation[key];
24842
+ }
24843
+ for (const key of ["tools", "toolConfig", "safetySettings"]) {
24844
+ const value = params[key] ?? config[key];
24845
+ if (value !== void 0) metadata[key] = value;
24846
+ }
24847
+ const cached = params.cachedContent ?? config.cachedContent;
24848
+ if (cached)
24849
+ metadata.cachedContent = typeof cached === "string" ? cached : cached.name;
24850
+ return { input: convertAttachments({ model, contents }), metadata };
24851
+ }
24852
+ function convertAttachments(value) {
24853
+ const convert = (node) => {
24854
+ if (Array.isArray(node)) return node.map(convert);
24855
+ if (!isObject(node)) return node;
24856
+ if (isObject(node.inlineData)) {
24857
+ const { data, mimeType } = node.inlineData;
24858
+ const processed = processInputAttachments({
24859
+ type: "file",
24860
+ file: { file_data: `data:${mimeType};base64,${data}` }
24861
+ });
24862
+ if (typeof processed.file.file_data === "string")
24863
+ throw new Error("Unable to convert Google inline data");
24864
+ return {
24865
+ ...node,
24866
+ inlineData: { ...node.inlineData, data: processed.file.file_data }
24867
+ };
24868
+ }
24869
+ return Object.fromEntries(
24870
+ Object.entries(node).map(([key, item]) => [key, convert(item)])
24871
+ );
24872
+ };
24873
+ try {
24874
+ return convert(value);
24875
+ } catch (error) {
24876
+ debugLogger.error(
24877
+ "Error converting Google Generative AI attachments:",
24878
+ error
24879
+ );
24880
+ return value;
24881
+ }
24882
+ }
24883
+ function logResponse(span, response) {
24884
+ const usage = response.usageMetadata;
24885
+ const metrics = {};
24886
+ if (usage) {
24887
+ if (usage.promptTokenCount !== void 0)
24888
+ metrics.prompt_tokens = usage.promptTokenCount;
24889
+ if (usage.candidatesTokenCount !== void 0 || usage.thoughtsTokenCount !== void 0)
24890
+ metrics.completion_tokens = (usage.candidatesTokenCount ?? 0) + (usage.thoughtsTokenCount ?? 0);
24891
+ if (usage.totalTokenCount !== void 0)
24892
+ metrics.tokens = usage.totalTokenCount;
24893
+ if (usage.cachedContentTokenCount !== void 0)
24894
+ metrics.prompt_cached_tokens = usage.cachedContentTokenCount;
24895
+ if (usage.thoughtsTokenCount !== void 0)
24896
+ metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
24897
+ }
24898
+ span.log({
24899
+ output: convertAttachments({
24900
+ candidates: response.candidates,
24901
+ promptFeedback: response.promptFeedback
24902
+ }),
24903
+ metrics,
24904
+ ...response.modelVersion ? { metadata: { model: response.modelVersion } } : {}
24905
+ });
24906
+ }
24907
+
24565
24908
  // src/instrumentation/plugins/google-genai-plugin.ts
24566
24909
  var GOOGLE_GENAI_INTERNAL_CONTEXT = {
24567
24910
  caller_filename: "<node-internal>",
@@ -26113,7 +26456,7 @@ var HuggingFaceTransformersPlugin = class extends BasePlugin {
26113
26456
  getTask(event)
26114
26457
  ),
26115
26458
  extractInput: (args, event) => ({
26116
- input: extractInput(
26459
+ input: extractInput2(
26117
26460
  getTask(event),
26118
26461
  args
26119
26462
  ),
@@ -26203,7 +26546,7 @@ function modelIdentifier(pipeline) {
26203
26546
  }
26204
26547
  return void 0;
26205
26548
  }
26206
- function extractInput(task, args) {
26549
+ function extractInput2(task, args) {
26207
26550
  switch (task) {
26208
26551
  case "feature-extraction":
26209
26552
  return args[0];
@@ -34638,6 +34981,458 @@ function logInstrumentationError5(context, error) {
34638
34981
  debugLogger.debug(`${context}:`, error);
34639
34982
  }
34640
34983
 
34984
+ // src/instrumentation/plugins/elevenlabs-plugin.ts
34985
+ var ElevenLabsPlugin = class extends BasePlugin {
34986
+ onEnable() {
34987
+ for (const method of [
34988
+ "convert",
34989
+ "stream",
34990
+ "convertWithTimestamps",
34991
+ "streamWithTimestamps"
34992
+ ]) {
34993
+ this.unsubscribers.push(
34994
+ interceptCall2(
34995
+ elevenLabsChannels[method],
34996
+ `elevenlabs.textToSpeech.${method}`,
34997
+ ([voice, request]) => ({
34998
+ input: {
34999
+ operation: "speech",
35000
+ prompt: request.text,
35001
+ parameters: {
35002
+ voice,
35003
+ format: request.outputFormat,
35004
+ language: request.languageCode,
35005
+ speed: request.voiceSettings?.speed
35006
+ }
35007
+ },
35008
+ metadata: {
35009
+ provider: "elevenlabs",
35010
+ model: request.modelId ?? "eleven_multilingual_v2"
35011
+ }
35012
+ }),
35013
+ (value, args, span, finish, headers, started) => captureSpeech(
35014
+ value,
35015
+ args[1],
35016
+ method,
35017
+ span,
35018
+ finish,
35019
+ started,
35020
+ headers
35021
+ )
35022
+ )
35023
+ );
35024
+ }
35025
+ this.unsubscribers.push(
35026
+ interceptCall2(
35027
+ elevenLabsChannels.transcribe,
35028
+ "elevenlabs.speechToText.convert",
35029
+ ([request]) => {
35030
+ if (request.webhook) return void 0;
35031
+ const file = request.file;
35032
+ const filename = typeof File !== "undefined" && file instanceof File ? file.name : "audio";
35033
+ const contentType = file instanceof Blob ? file.type || "application/octet-stream" : "application/octet-stream";
35034
+ const blob = file instanceof Blob ? file : file instanceof Uint8Array ? new Blob([new Uint8Array(file)], { type: contentType }) : file instanceof ArrayBuffer ? new Blob([file.slice(0)], { type: contentType }) : void 0;
35035
+ const fileData = blob ? new Attachment({ data: blob, filename, contentType }) : request.cloudStorageUrl;
35036
+ return {
35037
+ input: {
35038
+ operation: "transcribe",
35039
+ content: fileData ? [{ type: "file", file: { filename, file_data: fileData } }] : [],
35040
+ parameters: {
35041
+ language: request.languageCode,
35042
+ timestamp_granularities: request.timestampsGranularity
35043
+ }
35044
+ },
35045
+ metadata: { provider: "elevenlabs", model: request.modelId }
35046
+ };
35047
+ },
35048
+ (value, _args, span, finish) => {
35049
+ const result = value;
35050
+ const transcripts = result.transcripts ?? [result];
35051
+ span.log({
35052
+ output: {
35053
+ content: transcripts.flatMap(
35054
+ (transcript) => typeof transcript.text === "string" ? [{ type: "text", text: transcript.text }] : []
35055
+ ),
35056
+ annotations: {
35057
+ language: result.languageCode,
35058
+ words: result.words ?? (result.transcripts ? result.transcripts.flatMap(
35059
+ (transcript) => transcript.words ?? []
35060
+ ) : void 0)
35061
+ }
35062
+ }
35063
+ });
35064
+ finish();
35065
+ },
35066
+ ([request], span) => {
35067
+ const file = request.file;
35068
+ if (!isAsyncIterable(file)) return;
35069
+ const chunks = [];
35070
+ const filename = isObject(file) && typeof file.path === "string" ? file.path.split(/[\\/]/).pop() || "audio" : "audio";
35071
+ observeAudioStream(
35072
+ file,
35073
+ (chunk) => chunks.push(new Uint8Array(chunk)),
35074
+ () => {
35075
+ const contentType = "application/octet-stream";
35076
+ const data = new Blob(chunks, {
35077
+ type: contentType
35078
+ });
35079
+ chunks.length = 0;
35080
+ span.log({
35081
+ input: {
35082
+ content: [
35083
+ {
35084
+ type: "file",
35085
+ file: {
35086
+ filename,
35087
+ file_data: new Attachment({
35088
+ data,
35089
+ filename,
35090
+ contentType
35091
+ })
35092
+ }
35093
+ }
35094
+ ]
35095
+ }
35096
+ });
35097
+ },
35098
+ () => {
35099
+ chunks.length = 0;
35100
+ },
35101
+ span
35102
+ );
35103
+ }
35104
+ )
35105
+ );
35106
+ }
35107
+ onDisable() {
35108
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
35109
+ }
35110
+ };
35111
+ function interceptCall2(channel, name, input, output, beforeInvoke) {
35112
+ return channel.intercept((target, self, args) => {
35113
+ const invoke = () => Reflect.apply(target, self, args);
35114
+ if (isAutoInstrumentationSuppressed()) return invoke();
35115
+ const started = Date.now() / 1e3;
35116
+ let span;
35117
+ try {
35118
+ const event = input(args);
35119
+ if (event !== void 0)
35120
+ span = startSpan(
35121
+ withSpanInstrumentationName(
35122
+ {
35123
+ name,
35124
+ spanAttributes: { type: "llm" /* LLM */ },
35125
+ event
35126
+ },
35127
+ INSTRUMENTATION_NAMES.ELEVENLABS
35128
+ )
35129
+ );
35130
+ } catch (error) {
35131
+ debugLogger.error("Error starting ElevenLabs span", error);
35132
+ return invoke();
35133
+ }
35134
+ if (!span) return invoke();
35135
+ const activeSpan = span;
35136
+ let ended = false;
35137
+ const finish = (error) => {
35138
+ if (ended) return;
35139
+ ended = true;
35140
+ try {
35141
+ if (error !== void 0) activeSpan.log({ error });
35142
+ activeSpan.end();
35143
+ } catch (loggingError) {
35144
+ debugLogger.error("Error ending ElevenLabs span", loggingError);
35145
+ }
35146
+ };
35147
+ try {
35148
+ beforeInvoke?.(args, span);
35149
+ } catch (error) {
35150
+ debugLogger.error("Error observing ElevenLabs input", error);
35151
+ }
35152
+ let result;
35153
+ try {
35154
+ result = withCurrent(
35155
+ span,
35156
+ () => runWithAutoInstrumentationSuppressed(invoke)
35157
+ );
35158
+ } catch (error) {
35159
+ finish(error);
35160
+ throw error;
35161
+ }
35162
+ const capture = (value, headers) => {
35163
+ try {
35164
+ output(value, args, span, finish, headers, started);
35165
+ } catch (error) {
35166
+ debugLogger.error("Error capturing ElevenLabs output", error);
35167
+ finish();
35168
+ }
35169
+ };
35170
+ try {
35171
+ if (isObject(result) && typeof result.withRawResponse === "function") {
35172
+ void result.withRawResponse().then(
35173
+ ({
35174
+ data,
35175
+ rawResponse
35176
+ }) => capture(data, rawResponse?.headers),
35177
+ finish
35178
+ );
35179
+ } else {
35180
+ void Promise.resolve(result).then((value) => capture(value), finish);
35181
+ }
35182
+ } catch (error) {
35183
+ debugLogger.error("Error observing ElevenLabs result", error);
35184
+ finish();
35185
+ }
35186
+ return result;
35187
+ });
35188
+ }
35189
+ function captureSpeech(value, request, method, span, finish, started, headers) {
35190
+ const format = request.outputFormat ?? "mp3_44100_128";
35191
+ const formatType = format.startsWith("mp3_") ? "audio/mpeg" : format.startsWith("pcm_") ? "audio/pcm" : format.startsWith("opus_") ? "audio/ogg" : format.startsWith("ulaw_") ? "audio/basic" : format.startsWith("alaw_") ? "audio/x-alaw" : void 0;
35192
+ const headerType = headers?.get("content-type")?.split(";")[0];
35193
+ const contentType = headerType?.startsWith("audio/") ? headerType : formatType;
35194
+ const disposition = headers?.get("content-disposition");
35195
+ const headerFilename = disposition?.match(
35196
+ /filename="([^"]+)"|filename=([^;]+)/i
35197
+ );
35198
+ const filename = headerFilename?.[1] ?? headerFilename?.[2]?.trim() ?? `speech.${contentType ? getExtensionFromMediaType(contentType) : "bin"}`;
35199
+ const chunks = [];
35200
+ const alignments = [];
35201
+ let bytes = 0;
35202
+ let first = true;
35203
+ let stopped = false;
35204
+ const observe = (chunk) => {
35205
+ if (stopped || chunk.byteLength === 0) return;
35206
+ if (first && method.startsWith("stream")) {
35207
+ span.log({
35208
+ metrics: { time_to_first_token: Date.now() / 1e3 - started }
35209
+ });
35210
+ }
35211
+ first = false;
35212
+ chunks.push(new Uint8Array(chunk));
35213
+ bytes += chunk.byteLength;
35214
+ };
35215
+ const complete = () => {
35216
+ if (stopped) return;
35217
+ stopped = true;
35218
+ try {
35219
+ const content = [];
35220
+ if (contentType && bytes) {
35221
+ const data = new Uint8Array(bytes);
35222
+ let offset = 0;
35223
+ for (const chunk of chunks) {
35224
+ data.set(chunk, offset);
35225
+ offset += chunk.length;
35226
+ }
35227
+ content.push({
35228
+ type: "file",
35229
+ file: {
35230
+ filename,
35231
+ byte_size: bytes,
35232
+ file_data: new Attachment({
35233
+ data: new Blob([data], { type: contentType }),
35234
+ filename,
35235
+ contentType
35236
+ })
35237
+ }
35238
+ });
35239
+ }
35240
+ span.log({
35241
+ output: {
35242
+ content,
35243
+ ...alignments.length ? { annotations: alignments } : {}
35244
+ }
35245
+ });
35246
+ } finally {
35247
+ chunks.length = 0;
35248
+ finish();
35249
+ }
35250
+ };
35251
+ const cancel = (error) => {
35252
+ stopped = true;
35253
+ chunks.length = 0;
35254
+ finish(error);
35255
+ };
35256
+ const timestampChunk = (chunk) => {
35257
+ const binary = atob(chunk.audioBase64);
35258
+ observe(Uint8Array.from(binary, (character) => character.charCodeAt(0)));
35259
+ if (chunk.alignment || chunk.normalizedAlignment)
35260
+ alignments.push({
35261
+ alignment: chunk.alignment,
35262
+ normalized_alignment: chunk.normalizedAlignment
35263
+ });
35264
+ };
35265
+ if (method === "convertWithTimestamps") {
35266
+ timestampChunk(value);
35267
+ complete();
35268
+ } else if (method === "streamWithTimestamps") {
35269
+ patchStreamIfNeeded(value, {
35270
+ shouldCollect: (chunk) => {
35271
+ try {
35272
+ timestampChunk(chunk);
35273
+ } catch (error) {
35274
+ debugLogger.error("Error collecting ElevenLabs timestamps", error);
35275
+ cancel();
35276
+ }
35277
+ return false;
35278
+ },
35279
+ onComplete: complete,
35280
+ onCancel: () => cancel(),
35281
+ onError: cancel,
35282
+ aroundNext: (next) => withCurrent(span, next)
35283
+ });
35284
+ } else {
35285
+ observeAudioStream(value, observe, complete, cancel, span);
35286
+ }
35287
+ }
35288
+ function observeAudioStream(value, observe, complete, cancel, span) {
35289
+ let ended = false;
35290
+ const safeObserve = (chunk) => {
35291
+ if (ended) return;
35292
+ try {
35293
+ observe(chunk);
35294
+ } catch (error) {
35295
+ debugLogger.error("Error collecting ElevenLabs audio", error);
35296
+ end(false);
35297
+ }
35298
+ };
35299
+ const end = (success, error) => {
35300
+ if (ended) return;
35301
+ ended = true;
35302
+ try {
35303
+ if (success) complete();
35304
+ else cancel(error);
35305
+ } catch (loggingError) {
35306
+ debugLogger.error("Error logging ElevenLabs audio", loggingError);
35307
+ cancel();
35308
+ }
35309
+ };
35310
+ if (!isObject(value) || !Object.isExtensible(value)) {
35311
+ end(false);
35312
+ return;
35313
+ }
35314
+ if (typeof value.read === "function" && typeof value.on === "function") {
35315
+ value.on("end", () => end(true));
35316
+ value.on("close", () => end(false));
35317
+ const emit = value.emit;
35318
+ if (typeof emit === "function")
35319
+ value.emit = function(event, ...args) {
35320
+ if (event === "data" && args[0] instanceof Uint8Array)
35321
+ safeObserve(args[0]);
35322
+ if (event === "error") end(false, args[0]);
35323
+ return Reflect.apply(emit, this, [event, ...args]);
35324
+ };
35325
+ return;
35326
+ }
35327
+ if (typeof value.getReader === "function") {
35328
+ const webStream = value;
35329
+ const pipeTo = webStream.pipeTo;
35330
+ const pipeThrough = webStream.pipeThrough;
35331
+ webStream.pipeTo = function(destination, options) {
35332
+ if (!isObject(destination) || this.locked || destination.locked)
35333
+ return pipeTo.call(this, destination, options);
35334
+ const tap = new TransformStream({
35335
+ transform(chunk, controller) {
35336
+ safeObserve(chunk);
35337
+ controller.enqueue(chunk);
35338
+ },
35339
+ flush() {
35340
+ end(true);
35341
+ }
35342
+ });
35343
+ const observed = pipeThrough.call(
35344
+ this,
35345
+ tap,
35346
+ options
35347
+ );
35348
+ return observed.pipeTo(destination, options).catch((error) => {
35349
+ end(false, error);
35350
+ throw error;
35351
+ });
35352
+ };
35353
+ webStream.pipeThrough = function(transform, options) {
35354
+ if (this.locked || transform.writable.locked || transform.readable.locked)
35355
+ return pipeThrough.call(this, transform, options);
35356
+ const result = webStream.pipeTo.call(this, transform.writable, options);
35357
+ void result.catch(() => {
35358
+ });
35359
+ return transform.readable;
35360
+ };
35361
+ const getReader = value.getReader;
35362
+ value.getReader = function(...args) {
35363
+ const reader = Reflect.apply(getReader, this, args);
35364
+ const read2 = reader.read;
35365
+ reader.read = function(...readArgs) {
35366
+ return Promise.resolve(
35367
+ withCurrent(span, () => Reflect.apply(read2, this, readArgs))
35368
+ ).then(
35369
+ (result) => {
35370
+ if (result.value) safeObserve(result.value);
35371
+ if (result.done) end(true);
35372
+ return result;
35373
+ },
35374
+ (error) => {
35375
+ end(false, error);
35376
+ throw error;
35377
+ }
35378
+ );
35379
+ };
35380
+ const readerCancel = reader.cancel;
35381
+ reader.cancel = function(...cancelArgs) {
35382
+ const result = Reflect.apply(readerCancel, this, cancelArgs);
35383
+ end(false);
35384
+ return result;
35385
+ };
35386
+ return reader;
35387
+ };
35388
+ const streamCancel = value.cancel;
35389
+ if (typeof streamCancel === "function")
35390
+ value.cancel = function(...args) {
35391
+ const result = Reflect.apply(streamCancel, this, args);
35392
+ void Promise.resolve(result).then(
35393
+ () => end(false),
35394
+ () => {
35395
+ }
35396
+ );
35397
+ return result;
35398
+ };
35399
+ }
35400
+ if (typeof value.getReader === "function" && typeof value.values === "function") {
35401
+ const values = value.values;
35402
+ const iterate = function(...args) {
35403
+ const iterator = Reflect.apply(values, this, args);
35404
+ patchStreamIfNeeded(iterator, {
35405
+ shouldCollect(chunk) {
35406
+ safeObserve(chunk);
35407
+ return false;
35408
+ },
35409
+ onComplete: () => end(true),
35410
+ onCancel: () => end(false),
35411
+ onError: (error) => end(false, error),
35412
+ aroundNext: (next) => withCurrent(span, next)
35413
+ });
35414
+ return iterator;
35415
+ };
35416
+ value.values = iterate;
35417
+ Object.defineProperty(value, Symbol.asyncIterator, {
35418
+ configurable: true,
35419
+ writable: true,
35420
+ value: iterate
35421
+ });
35422
+ } else if (isAsyncIterable(value)) {
35423
+ patchStreamIfNeeded(value, {
35424
+ shouldCollect: (chunk) => {
35425
+ safeObserve(chunk);
35426
+ return false;
35427
+ },
35428
+ onComplete: () => end(true),
35429
+ onCancel: () => end(false),
35430
+ onError: (error) => end(false, error),
35431
+ aroundNext: (next) => withCurrent(span, next)
35432
+ });
35433
+ } else if (typeof value.getReader !== "function") end(false);
35434
+ }
35435
+
34641
35436
  // src/instrumentation/plugins/voyageai-plugin.ts
34642
35437
  var RERANK_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
34643
35438
  "model",
@@ -34681,7 +35476,7 @@ var VoyageAIPlugin = class extends BasePlugin {
34681
35476
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
34682
35477
  }
34683
35478
  };
34684
- function interceptVoyageAICall(channel, name, extractInput2, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
35479
+ function interceptVoyageAICall(channel, name, extractInput3, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
34685
35480
  return channel.intercept((target, thisArg, args) => {
34686
35481
  const invokeTarget = () => Reflect.apply(target, thisArg, args);
34687
35482
  if (isAutoInstrumentationSuppressed()) {
@@ -34689,7 +35484,7 @@ function interceptVoyageAICall(channel, name, extractInput2, extractOutput2, ext
34689
35484
  }
34690
35485
  let span;
34691
35486
  try {
34692
- const { input, metadata } = extractInput2(args);
35487
+ const { input, metadata } = extractInput3(args);
34693
35488
  span = startSpan(
34694
35489
  withSpanInstrumentationName(
34695
35490
  {
@@ -35460,6 +36255,7 @@ var BraintrustPlugin = class extends BasePlugin {
35460
36255
  cloudflareThinkPlugin = null;
35461
36256
  cursorSDKPlugin = null;
35462
36257
  openAIAgentsPlugin = null;
36258
+ googleGenerativeAIPlugin = null;
35463
36259
  googleGenAIPlugin = null;
35464
36260
  huggingFacePlugin = null;
35465
36261
  huggingFaceTransformersPlugin = null;
@@ -35478,6 +36274,7 @@ var BraintrustPlugin = class extends BasePlugin {
35478
36274
  langSmithPlugin = null;
35479
36275
  piCodingAgentPlugin = null;
35480
36276
  strandsAgentSDKPlugin = null;
36277
+ elevenLabsPlugin = null;
35481
36278
  voyageAIPlugin = null;
35482
36279
  cloudflareAIChatPlugin = null;
35483
36280
  cloudflareAgentsPlugin = null;
@@ -35519,6 +36316,10 @@ var BraintrustPlugin = class extends BasePlugin {
35519
36316
  this.openAIAgentsPlugin = new OpenAIAgentsPlugin();
35520
36317
  this.openAIAgentsPlugin.enable();
35521
36318
  }
36319
+ if (integrations.googleGenerativeAI !== false) {
36320
+ this.googleGenerativeAIPlugin = new GoogleGenerativeAIPlugin();
36321
+ this.googleGenerativeAIPlugin.enable();
36322
+ }
35522
36323
  if (integrations.googleGenAI !== false && integrations.google !== false) {
35523
36324
  this.googleGenAIPlugin = new GoogleGenAIPlugin();
35524
36325
  this.googleGenAIPlugin.enable();
@@ -35553,6 +36354,10 @@ var BraintrustPlugin = class extends BasePlugin {
35553
36354
  this.coherePlugin = new CoherePlugin();
35554
36355
  this.coherePlugin.enable();
35555
36356
  }
36357
+ if (integrations.elevenlabs !== false) {
36358
+ this.elevenLabsPlugin = new ElevenLabsPlugin();
36359
+ this.elevenLabsPlugin.enable();
36360
+ }
35556
36361
  if (integrations.voyageai !== false) {
35557
36362
  this.voyageAIPlugin = new VoyageAIPlugin();
35558
36363
  this.voyageAIPlugin.enable();
@@ -35637,6 +36442,10 @@ var BraintrustPlugin = class extends BasePlugin {
35637
36442
  this.openAIAgentsPlugin.disable();
35638
36443
  this.openAIAgentsPlugin = null;
35639
36444
  }
36445
+ if (this.googleGenerativeAIPlugin) {
36446
+ this.googleGenerativeAIPlugin.disable();
36447
+ this.googleGenerativeAIPlugin = null;
36448
+ }
35640
36449
  if (this.googleGenAIPlugin) {
35641
36450
  this.googleGenAIPlugin.disable();
35642
36451
  this.googleGenAIPlugin = null;
@@ -35673,6 +36482,10 @@ var BraintrustPlugin = class extends BasePlugin {
35673
36482
  this.coherePlugin.disable();
35674
36483
  this.coherePlugin = null;
35675
36484
  }
36485
+ if (this.elevenLabsPlugin) {
36486
+ this.elevenLabsPlugin.disable();
36487
+ this.elevenLabsPlugin = null;
36488
+ }
35676
36489
  if (this.voyageAIPlugin) {
35677
36490
  this.voyageAIPlugin.disable();
35678
36491
  this.voyageAIPlugin = null;