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
@@ -3115,6 +3115,14 @@ var ChatCompletionContentPartImageWithTitle = z6.object({
3115
3115
  ttl: z6.enum(["5m", "1h"]).optional()
3116
3116
  }).optional()
3117
3117
  });
3118
+ var ChatCompletionContentPartInputAudioWithTitle = z6.object({
3119
+ input_audio: z6.object({ data: z6.string(), format: z6.enum(["wav", "mp3"]) }),
3120
+ type: z6.literal("input_audio"),
3121
+ cache_control: z6.object({
3122
+ type: z6.literal("ephemeral"),
3123
+ ttl: z6.enum(["5m", "1h"]).optional()
3124
+ }).optional()
3125
+ });
3118
3126
  var ChatCompletionContentPartFileFile = z6.object({ file_data: z6.string(), filename: z6.string(), file_id: z6.string() }).partial();
3119
3127
  var ChatCompletionContentPartFileWithTitle = z6.object({
3120
3128
  file: ChatCompletionContentPartFileFile,
@@ -3127,6 +3135,7 @@ var ChatCompletionContentPartFileWithTitle = z6.object({
3127
3135
  var ChatCompletionContentPart = z6.union([
3128
3136
  ChatCompletionContentPartTextWithTitle,
3129
3137
  ChatCompletionContentPartImageWithTitle,
3138
+ ChatCompletionContentPartInputAudioWithTitle,
3130
3139
  ChatCompletionContentPartFileWithTitle
3131
3140
  ]);
3132
3141
  var ChatCompletionContentPartText = z6.object({
@@ -5954,6 +5963,7 @@ var INSTRUMENTATION_NAMES = {
5954
5963
  GENKIT: "genkit",
5955
5964
  GITHUB_COPILOT: "github-copilot",
5956
5965
  GOOGLE_ADK: "google-adk",
5966
+ GOOGLE_GENERATIVE_AI: "google-generative-ai",
5957
5967
  GOOGLE_GENAI: "google-genai",
5958
5968
  GROQ: "groq",
5959
5969
  HUGGINGFACE: "huggingface",
@@ -5969,12 +5979,13 @@ var INSTRUMENTATION_NAMES = {
5969
5979
  OPENROUTER_AGENT: "openrouter-agent",
5970
5980
  PI_CODING_AGENT: "pi-coding-agent",
5971
5981
  STRANDS_AGENT_SDK: "strands-agent-sdk",
5972
- VOYAGEAI: "voyageai"
5982
+ VOYAGEAI: "voyageai",
5983
+ ELEVENLABS: "elevenlabs"
5973
5984
  };
5974
5985
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5975
5986
  "braintrust.spanInstrumentationName"
5976
5987
  );
5977
- var SDK_VERSION = true ? "3.31.0" : "0.0.0";
5988
+ var SDK_VERSION = true ? "3.32.0" : "0.0.0";
5978
5989
  function withSpanInstrumentationName(args, instrumentationName) {
5979
5990
  return {
5980
5991
  ...args,
@@ -11148,6 +11159,16 @@ function renderMessageImpl(render, message, variables) {
11148
11159
  }
11149
11160
  }
11150
11161
  ];
11162
+ case "input_audio":
11163
+ return [
11164
+ {
11165
+ ...c,
11166
+ input_audio: {
11167
+ ...c.input_audio,
11168
+ data: render(c.input_audio.data)
11169
+ }
11170
+ }
11171
+ ];
11151
11172
  case "file":
11152
11173
  return [
11153
11174
  {
@@ -23640,6 +23661,342 @@ var OpenAIAgentsPlugin = class extends BasePlugin {
23640
23661
  }
23641
23662
  };
23642
23663
 
23664
+ // src/instrumentation/plugins/google-generative-ai-channels.ts
23665
+ var googleGenerativeAIChannels = defineChannels(
23666
+ "@google/generative-ai",
23667
+ {
23668
+ generateContent: channel({ channelName: "GenerativeModel.generateContent", kind: "async" }),
23669
+ generateContentStream: channel({ channelName: "GenerativeModel.generateContentStream", kind: "async" }),
23670
+ embedContent: channel({ channelName: "GenerativeModel.embedContent", kind: "async" }),
23671
+ batchEmbedContents: channel({ channelName: "GenerativeModel.batchEmbedContents", kind: "async" }),
23672
+ sendMessage: channel({ channelName: "ChatSession.sendMessage", kind: "async" }),
23673
+ sendMessageStream: channel({ channelName: "ChatSession.sendMessageStream", kind: "async" })
23674
+ },
23675
+ { instrumentationName: INSTRUMENTATION_NAMES.GOOGLE_GENERATIVE_AI }
23676
+ );
23677
+
23678
+ // src/instrumentation/plugins/google-generative-ai-plugin.ts
23679
+ var GENERATION_CONFIG_KEYS = [
23680
+ "temperature",
23681
+ "topP",
23682
+ "topK",
23683
+ "candidateCount",
23684
+ "maxOutputTokens",
23685
+ "stopSequences",
23686
+ "responseMimeType",
23687
+ "responseSchema",
23688
+ "presencePenalty",
23689
+ "frequencyPenalty",
23690
+ "responseLogprobs",
23691
+ "logprobs",
23692
+ "thinkingConfig"
23693
+ ];
23694
+ var GoogleGenerativeAIPlugin = class extends BasePlugin {
23695
+ onEnable() {
23696
+ this.unsubscribers.push(
23697
+ interceptCall(
23698
+ googleGenerativeAIChannels.generateContent,
23699
+ "generateContent"
23700
+ ),
23701
+ interceptCall(
23702
+ googleGenerativeAIChannels.generateContentStream,
23703
+ "generateContentStream"
23704
+ ),
23705
+ interceptCall(googleGenerativeAIChannels.sendMessage, "sendMessage"),
23706
+ interceptCall(
23707
+ googleGenerativeAIChannels.sendMessageStream,
23708
+ "sendMessageStream"
23709
+ ),
23710
+ interceptCall(googleGenerativeAIChannels.embedContent, "embedContent"),
23711
+ interceptCall(
23712
+ googleGenerativeAIChannels.batchEmbedContents,
23713
+ "batchEmbedContents"
23714
+ )
23715
+ );
23716
+ }
23717
+ onDisable() {
23718
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
23719
+ }
23720
+ };
23721
+ function interceptCall(channel2, operation) {
23722
+ return channel2.intercept((target, thisArg, args) => {
23723
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
23724
+ if (isAutoInstrumentationSuppressed()) return invokeTarget();
23725
+ const self = thisArg;
23726
+ const chat = operation.startsWith("sendMessage");
23727
+ const embedding = operation === "embedContent" || operation === "batchEmbedContents";
23728
+ const start = getCurrentUnixTimestamp();
23729
+ let span;
23730
+ try {
23731
+ span = startSpan(
23732
+ withSpanInstrumentationName(
23733
+ {
23734
+ name: embedding ? operation === "embedContent" ? "embed_content" : "batch_embed_contents" : "generate_content",
23735
+ spanAttributes: { type: "llm" /* LLM */ },
23736
+ event: extractInput(self, args[0], operation)
23737
+ },
23738
+ INSTRUMENTATION_NAMES.GOOGLE_GENERATIVE_AI
23739
+ )
23740
+ );
23741
+ } catch (error) {
23742
+ debugLogger.error("Error starting Google Generative AI span:", error);
23743
+ return invokeTarget();
23744
+ }
23745
+ let ended = false;
23746
+ const finish = (log2) => {
23747
+ if (ended) return;
23748
+ ended = true;
23749
+ try {
23750
+ log2();
23751
+ } catch (error) {
23752
+ debugLogger.error("Error logging Google Generative AI span:", error);
23753
+ }
23754
+ try {
23755
+ span.end();
23756
+ } catch (error) {
23757
+ debugLogger.error("Error ending Google Generative AI span:", error);
23758
+ }
23759
+ };
23760
+ if (chat) {
23761
+ try {
23762
+ void self._sendPromise.then(
23763
+ () => {
23764
+ try {
23765
+ span.log(extractInput(self, args[0], operation));
23766
+ } catch (error) {
23767
+ debugLogger.error("Error capturing Google chat history:", error);
23768
+ }
23769
+ },
23770
+ () => {
23771
+ }
23772
+ );
23773
+ } catch (error) {
23774
+ debugLogger.error("Error observing Google chat history:", error);
23775
+ }
23776
+ }
23777
+ let result;
23778
+ try {
23779
+ result = withCurrent(
23780
+ span,
23781
+ () => runWithAutoInstrumentationSuppressed(invokeTarget)
23782
+ );
23783
+ } catch (error) {
23784
+ finish(() => span.log({ error }));
23785
+ throw error;
23786
+ }
23787
+ void Promise.resolve(result).then(
23788
+ (value) => {
23789
+ try {
23790
+ if ("stream" in value) {
23791
+ let firstToken = false;
23792
+ const partial = { candidates: [] };
23793
+ const candidates = /* @__PURE__ */ new Map();
23794
+ patchStreamIfNeeded(value.stream, {
23795
+ aroundNext: (callback) => withCurrent(span, callback),
23796
+ onChunk: (chunk) => {
23797
+ for (const candidate of chunk.candidates ?? []) {
23798
+ const index = candidate.index ?? 0;
23799
+ const previous = candidates.get(index);
23800
+ const parts = [...previous?.content?.parts ?? []];
23801
+ for (const part of candidate.content?.parts ?? []) {
23802
+ const last = parts[parts.length - 1];
23803
+ if (part.text !== void 0 && last?.text !== void 0) {
23804
+ parts[parts.length - 1] = {
23805
+ ...last,
23806
+ text: last.text + part.text
23807
+ };
23808
+ } else parts.push(part);
23809
+ }
23810
+ candidates.set(index, {
23811
+ ...previous,
23812
+ ...candidate,
23813
+ content: {
23814
+ role: candidate.content?.role ?? previous?.content?.role ?? "model",
23815
+ parts
23816
+ }
23817
+ });
23818
+ }
23819
+ partial.candidates = Array.from(candidates.values());
23820
+ if (chunk.usageMetadata)
23821
+ partial.usageMetadata = chunk.usageMetadata;
23822
+ if (!firstToken && chunk.candidates?.some(
23823
+ (candidate) => candidate.content?.parts.some(
23824
+ (part) => part.text !== void 0 ? part.text.length > 0 : Object.keys(part).length > 0
23825
+ )
23826
+ )) {
23827
+ firstToken = true;
23828
+ span.log({
23829
+ metrics: {
23830
+ time_to_first_token: getCurrentUnixTimestamp() - start
23831
+ }
23832
+ });
23833
+ }
23834
+ },
23835
+ onComplete: () => {
23836
+ },
23837
+ onError: (error) => finish(() => {
23838
+ logResponse(span, partial);
23839
+ span.log({ error });
23840
+ }),
23841
+ onCancel: () => finish(() => logResponse(span, partial))
23842
+ });
23843
+ void value.response.then(
23844
+ (response) => finish(() => logResponse(span, response)),
23845
+ (error) => finish(() => {
23846
+ logResponse(span, partial);
23847
+ span.log({ error });
23848
+ })
23849
+ );
23850
+ } else if ("response" in value) {
23851
+ finish(() => logResponse(span, value.response));
23852
+ } else {
23853
+ const metrics = {};
23854
+ const promptTokens = value.usageMetadata?.promptTokenCount;
23855
+ if (typeof promptTokens === "number" && Number.isFinite(promptTokens) && promptTokens >= 0) {
23856
+ metrics.prompt_tokens = promptTokens;
23857
+ metrics.tokens = promptTokens;
23858
+ }
23859
+ for (const detail of value.usageMetadata?.promptTokenDetails ?? []) {
23860
+ if (detail.modality === "AUDIO" && typeof detail.tokenCount === "number" && Number.isFinite(detail.tokenCount) && detail.tokenCount >= 0) {
23861
+ metrics.prompt_audio_tokens = (metrics.prompt_audio_tokens ?? 0) + detail.tokenCount;
23862
+ }
23863
+ }
23864
+ finish(
23865
+ () => span.log({
23866
+ metrics,
23867
+ output: {
23868
+ count: value.embeddings?.length ?? (value.embedding ? 1 : 0)
23869
+ }
23870
+ })
23871
+ );
23872
+ }
23873
+ } catch (error) {
23874
+ debugLogger.error(
23875
+ "Error observing Google Generative AI result:",
23876
+ error
23877
+ );
23878
+ finish(() => {
23879
+ });
23880
+ }
23881
+ },
23882
+ (error) => finish(() => span.log({ error }))
23883
+ );
23884
+ return result;
23885
+ });
23886
+ }
23887
+ function normalizeContent(message) {
23888
+ const parts = (typeof message === "string" ? [message] : message).map(
23889
+ (part) => typeof part === "string" ? { text: part } : part
23890
+ );
23891
+ return {
23892
+ role: parts.some((part) => part.functionResponse) ? "function" : "user",
23893
+ parts
23894
+ };
23895
+ }
23896
+ function extractInput(self, request, operation) {
23897
+ const model = self.model.replace(/^models\//, "");
23898
+ if (operation === "embedContent" || operation === "batchEmbedContents") {
23899
+ const requests = operation === "batchEmbedContents" ? request.requests : [
23900
+ typeof request === "string" || Array.isArray(request) ? { content: normalizeContent(request) } : request
23901
+ ];
23902
+ const dimensions = requests[0]?.outputDimensionality;
23903
+ return {
23904
+ input: {
23905
+ inputs: convertAttachments(requests).map((item) => ({
23906
+ content: item.content.parts.length === 1 && item.content.parts[0].text !== void 0 ? item.content.parts[0].text : item.content.parts.map((part) => {
23907
+ if (part.text !== void 0)
23908
+ return { type: "text", text: part.text };
23909
+ const mimeType = part.inlineData?.mimeType ?? part.fileData?.mimeType;
23910
+ const data = part.inlineData ? typeof part.inlineData.data === "string" ? `data:${mimeType};base64,${part.inlineData.data}` : part.inlineData.data : part.fileData?.fileUri;
23911
+ return mimeType?.startsWith("image/") ? { type: "image_url", image_url: { url: data } } : { type: "file", file: { file_data: data } };
23912
+ })
23913
+ })),
23914
+ ...dimensions !== void 0 && requests.every((item) => item.outputDimensionality === dimensions) ? { output_dimensions: dimensions } : {}
23915
+ },
23916
+ metadata: { model, provider: "google" }
23917
+ };
23918
+ }
23919
+ const chat = operation.startsWith("sendMessage");
23920
+ const config = chat ? self.params ?? {} : self;
23921
+ const params = typeof request === "string" || Array.isArray(request) ? { contents: [normalizeContent(request)] } : request;
23922
+ const system = params.systemInstruction ?? config.systemInstruction;
23923
+ const systemContent = typeof system === "string" ? { role: "system", parts: [{ text: system }] } : system && "parts" in system ? { ...system, role: "system" } : system ? { role: "system", parts: [system] } : void 0;
23924
+ const contents = [
23925
+ ...systemContent ? [systemContent] : [],
23926
+ ...chat ? self._history : [],
23927
+ ...params.contents
23928
+ ];
23929
+ const metadata = { model, provider: "google" };
23930
+ const generation = params.generationConfig ?? config.generationConfig;
23931
+ for (const key of GENERATION_CONFIG_KEYS) {
23932
+ if (generation && Object.hasOwn(generation, key))
23933
+ metadata[key] = generation[key];
23934
+ }
23935
+ for (const key of ["tools", "toolConfig", "safetySettings"]) {
23936
+ const value = params[key] ?? config[key];
23937
+ if (value !== void 0) metadata[key] = value;
23938
+ }
23939
+ const cached = params.cachedContent ?? config.cachedContent;
23940
+ if (cached)
23941
+ metadata.cachedContent = typeof cached === "string" ? cached : cached.name;
23942
+ return { input: convertAttachments({ model, contents }), metadata };
23943
+ }
23944
+ function convertAttachments(value) {
23945
+ const convert = (node) => {
23946
+ if (Array.isArray(node)) return node.map(convert);
23947
+ if (!isObject(node)) return node;
23948
+ if (isObject(node.inlineData)) {
23949
+ const { data, mimeType } = node.inlineData;
23950
+ const processed = processInputAttachments({
23951
+ type: "file",
23952
+ file: { file_data: `data:${mimeType};base64,${data}` }
23953
+ });
23954
+ if (typeof processed.file.file_data === "string")
23955
+ throw new Error("Unable to convert Google inline data");
23956
+ return {
23957
+ ...node,
23958
+ inlineData: { ...node.inlineData, data: processed.file.file_data }
23959
+ };
23960
+ }
23961
+ return Object.fromEntries(
23962
+ Object.entries(node).map(([key, item]) => [key, convert(item)])
23963
+ );
23964
+ };
23965
+ try {
23966
+ return convert(value);
23967
+ } catch (error) {
23968
+ debugLogger.error(
23969
+ "Error converting Google Generative AI attachments:",
23970
+ error
23971
+ );
23972
+ return value;
23973
+ }
23974
+ }
23975
+ function logResponse(span, response) {
23976
+ const usage = response.usageMetadata;
23977
+ const metrics = {};
23978
+ if (usage) {
23979
+ if (usage.promptTokenCount !== void 0)
23980
+ metrics.prompt_tokens = usage.promptTokenCount;
23981
+ if (usage.candidatesTokenCount !== void 0 || usage.thoughtsTokenCount !== void 0)
23982
+ metrics.completion_tokens = (usage.candidatesTokenCount ?? 0) + (usage.thoughtsTokenCount ?? 0);
23983
+ if (usage.totalTokenCount !== void 0)
23984
+ metrics.tokens = usage.totalTokenCount;
23985
+ if (usage.cachedContentTokenCount !== void 0)
23986
+ metrics.prompt_cached_tokens = usage.cachedContentTokenCount;
23987
+ if (usage.thoughtsTokenCount !== void 0)
23988
+ metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
23989
+ }
23990
+ span.log({
23991
+ output: convertAttachments({
23992
+ candidates: response.candidates,
23993
+ promptFeedback: response.promptFeedback
23994
+ }),
23995
+ metrics,
23996
+ ...response.modelVersion ? { metadata: { model: response.modelVersion } } : {}
23997
+ });
23998
+ }
23999
+
23643
24000
  // src/instrumentation/plugins/google-genai-channels.ts
23644
24001
  var googleGenAIChannels = defineChannels(
23645
24002
  "@google/genai",
@@ -25283,7 +25640,7 @@ var HuggingFaceTransformersPlugin = class extends BasePlugin {
25283
25640
  getTask(event)
25284
25641
  ),
25285
25642
  extractInput: (args, event) => ({
25286
- input: extractInput(
25643
+ input: extractInput2(
25287
25644
  getTask(event),
25288
25645
  args
25289
25646
  ),
@@ -25373,7 +25730,7 @@ function modelIdentifier(pipeline) {
25373
25730
  }
25374
25731
  return void 0;
25375
25732
  }
25376
- function extractInput(task, args) {
25733
+ function extractInput2(task, args) {
25377
25734
  switch (task) {
25378
25735
  case "feature-extraction":
25379
25736
  return args[0];
@@ -35727,6 +36084,477 @@ function logInstrumentationError5(context, error) {
35727
36084
  debugLogger.debug(`${context}:`, error);
35728
36085
  }
35729
36086
 
36087
+ // src/instrumentation/plugins/elevenlabs-channels.ts
36088
+ var elevenLabsChannels = defineChannels(
36089
+ "@elevenlabs/elevenlabs-js",
36090
+ {
36091
+ convert: channel({
36092
+ channelName: "textToSpeech.convert",
36093
+ kind: "async"
36094
+ }),
36095
+ stream: channel({
36096
+ channelName: "textToSpeech.stream",
36097
+ kind: "async"
36098
+ }),
36099
+ convertWithTimestamps: channel({ channelName: "textToSpeech.convertWithTimestamps", kind: "async" }),
36100
+ streamWithTimestamps: channel({ channelName: "textToSpeech.streamWithTimestamps", kind: "async" }),
36101
+ transcribe: channel({ channelName: "speechToText.convert", kind: "async" })
36102
+ },
36103
+ { instrumentationName: INSTRUMENTATION_NAMES.ELEVENLABS }
36104
+ );
36105
+
36106
+ // src/instrumentation/plugins/elevenlabs-plugin.ts
36107
+ var ElevenLabsPlugin = class extends BasePlugin {
36108
+ onEnable() {
36109
+ for (const method of [
36110
+ "convert",
36111
+ "stream",
36112
+ "convertWithTimestamps",
36113
+ "streamWithTimestamps"
36114
+ ]) {
36115
+ this.unsubscribers.push(
36116
+ interceptCall2(
36117
+ elevenLabsChannels[method],
36118
+ `elevenlabs.textToSpeech.${method}`,
36119
+ ([voice, request]) => ({
36120
+ input: {
36121
+ operation: "speech",
36122
+ prompt: request.text,
36123
+ parameters: {
36124
+ voice,
36125
+ format: request.outputFormat,
36126
+ language: request.languageCode,
36127
+ speed: request.voiceSettings?.speed
36128
+ }
36129
+ },
36130
+ metadata: {
36131
+ provider: "elevenlabs",
36132
+ model: request.modelId ?? "eleven_multilingual_v2"
36133
+ }
36134
+ }),
36135
+ (value, args, span, finish, headers, started) => captureSpeech(
36136
+ value,
36137
+ args[1],
36138
+ method,
36139
+ span,
36140
+ finish,
36141
+ started,
36142
+ headers
36143
+ )
36144
+ )
36145
+ );
36146
+ }
36147
+ this.unsubscribers.push(
36148
+ interceptCall2(
36149
+ elevenLabsChannels.transcribe,
36150
+ "elevenlabs.speechToText.convert",
36151
+ ([request]) => {
36152
+ if (request.webhook) return void 0;
36153
+ const file = request.file;
36154
+ const filename = typeof File !== "undefined" && file instanceof File ? file.name : "audio";
36155
+ const contentType = file instanceof Blob ? file.type || "application/octet-stream" : "application/octet-stream";
36156
+ 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;
36157
+ const fileData = blob ? new Attachment({ data: blob, filename, contentType }) : request.cloudStorageUrl;
36158
+ return {
36159
+ input: {
36160
+ operation: "transcribe",
36161
+ content: fileData ? [{ type: "file", file: { filename, file_data: fileData } }] : [],
36162
+ parameters: {
36163
+ language: request.languageCode,
36164
+ timestamp_granularities: request.timestampsGranularity
36165
+ }
36166
+ },
36167
+ metadata: { provider: "elevenlabs", model: request.modelId }
36168
+ };
36169
+ },
36170
+ (value, _args, span, finish) => {
36171
+ const result = value;
36172
+ const transcripts = result.transcripts ?? [result];
36173
+ span.log({
36174
+ output: {
36175
+ content: transcripts.flatMap(
36176
+ (transcript) => typeof transcript.text === "string" ? [{ type: "text", text: transcript.text }] : []
36177
+ ),
36178
+ annotations: {
36179
+ language: result.languageCode,
36180
+ words: result.words ?? (result.transcripts ? result.transcripts.flatMap(
36181
+ (transcript) => transcript.words ?? []
36182
+ ) : void 0)
36183
+ }
36184
+ }
36185
+ });
36186
+ finish();
36187
+ },
36188
+ ([request], span) => {
36189
+ const file = request.file;
36190
+ if (!isAsyncIterable(file)) return;
36191
+ const chunks = [];
36192
+ const filename = isObject(file) && typeof file.path === "string" ? file.path.split(/[\\/]/).pop() || "audio" : "audio";
36193
+ observeAudioStream(
36194
+ file,
36195
+ (chunk) => chunks.push(new Uint8Array(chunk)),
36196
+ () => {
36197
+ const contentType = "application/octet-stream";
36198
+ const data = new Blob(chunks, {
36199
+ type: contentType
36200
+ });
36201
+ chunks.length = 0;
36202
+ span.log({
36203
+ input: {
36204
+ content: [
36205
+ {
36206
+ type: "file",
36207
+ file: {
36208
+ filename,
36209
+ file_data: new Attachment({
36210
+ data,
36211
+ filename,
36212
+ contentType
36213
+ })
36214
+ }
36215
+ }
36216
+ ]
36217
+ }
36218
+ });
36219
+ },
36220
+ () => {
36221
+ chunks.length = 0;
36222
+ },
36223
+ span
36224
+ );
36225
+ }
36226
+ )
36227
+ );
36228
+ }
36229
+ onDisable() {
36230
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
36231
+ }
36232
+ };
36233
+ function interceptCall2(channel2, name, input, output, beforeInvoke) {
36234
+ return channel2.intercept((target, self, args) => {
36235
+ const invoke2 = () => Reflect.apply(target, self, args);
36236
+ if (isAutoInstrumentationSuppressed()) return invoke2();
36237
+ const started = Date.now() / 1e3;
36238
+ let span;
36239
+ try {
36240
+ const event = input(args);
36241
+ if (event !== void 0)
36242
+ span = startSpan(
36243
+ withSpanInstrumentationName(
36244
+ {
36245
+ name,
36246
+ spanAttributes: { type: "llm" /* LLM */ },
36247
+ event
36248
+ },
36249
+ INSTRUMENTATION_NAMES.ELEVENLABS
36250
+ )
36251
+ );
36252
+ } catch (error) {
36253
+ debugLogger.error("Error starting ElevenLabs span", error);
36254
+ return invoke2();
36255
+ }
36256
+ if (!span) return invoke2();
36257
+ const activeSpan = span;
36258
+ let ended = false;
36259
+ const finish = (error) => {
36260
+ if (ended) return;
36261
+ ended = true;
36262
+ try {
36263
+ if (error !== void 0) activeSpan.log({ error });
36264
+ activeSpan.end();
36265
+ } catch (loggingError) {
36266
+ debugLogger.error("Error ending ElevenLabs span", loggingError);
36267
+ }
36268
+ };
36269
+ try {
36270
+ beforeInvoke?.(args, span);
36271
+ } catch (error) {
36272
+ debugLogger.error("Error observing ElevenLabs input", error);
36273
+ }
36274
+ let result;
36275
+ try {
36276
+ result = withCurrent(
36277
+ span,
36278
+ () => runWithAutoInstrumentationSuppressed(invoke2)
36279
+ );
36280
+ } catch (error) {
36281
+ finish(error);
36282
+ throw error;
36283
+ }
36284
+ const capture = (value, headers) => {
36285
+ try {
36286
+ output(value, args, span, finish, headers, started);
36287
+ } catch (error) {
36288
+ debugLogger.error("Error capturing ElevenLabs output", error);
36289
+ finish();
36290
+ }
36291
+ };
36292
+ try {
36293
+ if (isObject(result) && typeof result.withRawResponse === "function") {
36294
+ void result.withRawResponse().then(
36295
+ ({
36296
+ data,
36297
+ rawResponse
36298
+ }) => capture(data, rawResponse?.headers),
36299
+ finish
36300
+ );
36301
+ } else {
36302
+ void Promise.resolve(result).then((value) => capture(value), finish);
36303
+ }
36304
+ } catch (error) {
36305
+ debugLogger.error("Error observing ElevenLabs result", error);
36306
+ finish();
36307
+ }
36308
+ return result;
36309
+ });
36310
+ }
36311
+ function captureSpeech(value, request, method, span, finish, started, headers) {
36312
+ const format = request.outputFormat ?? "mp3_44100_128";
36313
+ 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;
36314
+ const headerType = headers?.get("content-type")?.split(";")[0];
36315
+ const contentType = headerType?.startsWith("audio/") ? headerType : formatType;
36316
+ const disposition = headers?.get("content-disposition");
36317
+ const headerFilename = disposition?.match(
36318
+ /filename="([^"]+)"|filename=([^;]+)/i
36319
+ );
36320
+ const filename = headerFilename?.[1] ?? headerFilename?.[2]?.trim() ?? `speech.${contentType ? getExtensionFromMediaType(contentType) : "bin"}`;
36321
+ const chunks = [];
36322
+ const alignments = [];
36323
+ let bytes = 0;
36324
+ let first = true;
36325
+ let stopped = false;
36326
+ const observe = (chunk) => {
36327
+ if (stopped || chunk.byteLength === 0) return;
36328
+ if (first && method.startsWith("stream")) {
36329
+ span.log({
36330
+ metrics: { time_to_first_token: Date.now() / 1e3 - started }
36331
+ });
36332
+ }
36333
+ first = false;
36334
+ chunks.push(new Uint8Array(chunk));
36335
+ bytes += chunk.byteLength;
36336
+ };
36337
+ const complete = () => {
36338
+ if (stopped) return;
36339
+ stopped = true;
36340
+ try {
36341
+ const content = [];
36342
+ if (contentType && bytes) {
36343
+ const data = new Uint8Array(bytes);
36344
+ let offset = 0;
36345
+ for (const chunk of chunks) {
36346
+ data.set(chunk, offset);
36347
+ offset += chunk.length;
36348
+ }
36349
+ content.push({
36350
+ type: "file",
36351
+ file: {
36352
+ filename,
36353
+ byte_size: bytes,
36354
+ file_data: new Attachment({
36355
+ data: new Blob([data], { type: contentType }),
36356
+ filename,
36357
+ contentType
36358
+ })
36359
+ }
36360
+ });
36361
+ }
36362
+ span.log({
36363
+ output: {
36364
+ content,
36365
+ ...alignments.length ? { annotations: alignments } : {}
36366
+ }
36367
+ });
36368
+ } finally {
36369
+ chunks.length = 0;
36370
+ finish();
36371
+ }
36372
+ };
36373
+ const cancel = (error) => {
36374
+ stopped = true;
36375
+ chunks.length = 0;
36376
+ finish(error);
36377
+ };
36378
+ const timestampChunk = (chunk) => {
36379
+ const binary = atob(chunk.audioBase64);
36380
+ observe(Uint8Array.from(binary, (character) => character.charCodeAt(0)));
36381
+ if (chunk.alignment || chunk.normalizedAlignment)
36382
+ alignments.push({
36383
+ alignment: chunk.alignment,
36384
+ normalized_alignment: chunk.normalizedAlignment
36385
+ });
36386
+ };
36387
+ if (method === "convertWithTimestamps") {
36388
+ timestampChunk(value);
36389
+ complete();
36390
+ } else if (method === "streamWithTimestamps") {
36391
+ patchStreamIfNeeded(value, {
36392
+ shouldCollect: (chunk) => {
36393
+ try {
36394
+ timestampChunk(chunk);
36395
+ } catch (error) {
36396
+ debugLogger.error("Error collecting ElevenLabs timestamps", error);
36397
+ cancel();
36398
+ }
36399
+ return false;
36400
+ },
36401
+ onComplete: complete,
36402
+ onCancel: () => cancel(),
36403
+ onError: cancel,
36404
+ aroundNext: (next) => withCurrent(span, next)
36405
+ });
36406
+ } else {
36407
+ observeAudioStream(value, observe, complete, cancel, span);
36408
+ }
36409
+ }
36410
+ function observeAudioStream(value, observe, complete, cancel, span) {
36411
+ let ended = false;
36412
+ const safeObserve = (chunk) => {
36413
+ if (ended) return;
36414
+ try {
36415
+ observe(chunk);
36416
+ } catch (error) {
36417
+ debugLogger.error("Error collecting ElevenLabs audio", error);
36418
+ end(false);
36419
+ }
36420
+ };
36421
+ const end = (success, error) => {
36422
+ if (ended) return;
36423
+ ended = true;
36424
+ try {
36425
+ if (success) complete();
36426
+ else cancel(error);
36427
+ } catch (loggingError) {
36428
+ debugLogger.error("Error logging ElevenLabs audio", loggingError);
36429
+ cancel();
36430
+ }
36431
+ };
36432
+ if (!isObject(value) || !Object.isExtensible(value)) {
36433
+ end(false);
36434
+ return;
36435
+ }
36436
+ if (typeof value.read === "function" && typeof value.on === "function") {
36437
+ value.on("end", () => end(true));
36438
+ value.on("close", () => end(false));
36439
+ const emit2 = value.emit;
36440
+ if (typeof emit2 === "function")
36441
+ value.emit = function(event, ...args) {
36442
+ if (event === "data" && args[0] instanceof Uint8Array)
36443
+ safeObserve(args[0]);
36444
+ if (event === "error") end(false, args[0]);
36445
+ return Reflect.apply(emit2, this, [event, ...args]);
36446
+ };
36447
+ return;
36448
+ }
36449
+ if (typeof value.getReader === "function") {
36450
+ const webStream = value;
36451
+ const pipeTo = webStream.pipeTo;
36452
+ const pipeThrough = webStream.pipeThrough;
36453
+ webStream.pipeTo = function(destination, options) {
36454
+ if (!isObject(destination) || this.locked || destination.locked)
36455
+ return pipeTo.call(this, destination, options);
36456
+ const tap = new TransformStream({
36457
+ transform(chunk, controller) {
36458
+ safeObserve(chunk);
36459
+ controller.enqueue(chunk);
36460
+ },
36461
+ flush() {
36462
+ end(true);
36463
+ }
36464
+ });
36465
+ const observed = pipeThrough.call(
36466
+ this,
36467
+ tap,
36468
+ options
36469
+ );
36470
+ return observed.pipeTo(destination, options).catch((error) => {
36471
+ end(false, error);
36472
+ throw error;
36473
+ });
36474
+ };
36475
+ webStream.pipeThrough = function(transform, options) {
36476
+ if (this.locked || transform.writable.locked || transform.readable.locked)
36477
+ return pipeThrough.call(this, transform, options);
36478
+ const result = webStream.pipeTo.call(this, transform.writable, options);
36479
+ void result.catch(() => {
36480
+ });
36481
+ return transform.readable;
36482
+ };
36483
+ const getReader = value.getReader;
36484
+ value.getReader = function(...args) {
36485
+ const reader = Reflect.apply(getReader, this, args);
36486
+ const read2 = reader.read;
36487
+ reader.read = function(...readArgs) {
36488
+ return Promise.resolve(
36489
+ withCurrent(span, () => Reflect.apply(read2, this, readArgs))
36490
+ ).then(
36491
+ (result) => {
36492
+ if (result.value) safeObserve(result.value);
36493
+ if (result.done) end(true);
36494
+ return result;
36495
+ },
36496
+ (error) => {
36497
+ end(false, error);
36498
+ throw error;
36499
+ }
36500
+ );
36501
+ };
36502
+ const readerCancel = reader.cancel;
36503
+ reader.cancel = function(...cancelArgs) {
36504
+ const result = Reflect.apply(readerCancel, this, cancelArgs);
36505
+ end(false);
36506
+ return result;
36507
+ };
36508
+ return reader;
36509
+ };
36510
+ const streamCancel = value.cancel;
36511
+ if (typeof streamCancel === "function")
36512
+ value.cancel = function(...args) {
36513
+ const result = Reflect.apply(streamCancel, this, args);
36514
+ void Promise.resolve(result).then(
36515
+ () => end(false),
36516
+ () => {
36517
+ }
36518
+ );
36519
+ return result;
36520
+ };
36521
+ }
36522
+ if (typeof value.getReader === "function" && typeof value.values === "function") {
36523
+ const values = value.values;
36524
+ const iterate = function(...args) {
36525
+ const iterator = Reflect.apply(values, this, args);
36526
+ patchStreamIfNeeded(iterator, {
36527
+ shouldCollect(chunk) {
36528
+ safeObserve(chunk);
36529
+ return false;
36530
+ },
36531
+ onComplete: () => end(true),
36532
+ onCancel: () => end(false),
36533
+ onError: (error) => end(false, error),
36534
+ aroundNext: (next) => withCurrent(span, next)
36535
+ });
36536
+ return iterator;
36537
+ };
36538
+ value.values = iterate;
36539
+ Object.defineProperty(value, Symbol.asyncIterator, {
36540
+ configurable: true,
36541
+ writable: true,
36542
+ value: iterate
36543
+ });
36544
+ } else if (isAsyncIterable(value)) {
36545
+ patchStreamIfNeeded(value, {
36546
+ shouldCollect: (chunk) => {
36547
+ safeObserve(chunk);
36548
+ return false;
36549
+ },
36550
+ onComplete: () => end(true),
36551
+ onCancel: () => end(false),
36552
+ onError: (error) => end(false, error),
36553
+ aroundNext: (next) => withCurrent(span, next)
36554
+ });
36555
+ } else if (typeof value.getReader !== "function") end(false);
36556
+ }
36557
+
35730
36558
  // src/instrumentation/plugins/voyageai-channels.ts
35731
36559
  var voyageAIChannels = defineChannels(
35732
36560
  "voyageai",
@@ -35794,7 +36622,7 @@ var VoyageAIPlugin = class extends BasePlugin {
35794
36622
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
35795
36623
  }
35796
36624
  };
35797
- function interceptVoyageAICall(channel2, name, extractInput2, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
36625
+ function interceptVoyageAICall(channel2, name, extractInput3, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
35798
36626
  return channel2.intercept((target, thisArg, args) => {
35799
36627
  const invokeTarget = () => Reflect.apply(target, thisArg, args);
35800
36628
  if (isAutoInstrumentationSuppressed()) {
@@ -35802,7 +36630,7 @@ function interceptVoyageAICall(channel2, name, extractInput2, extractOutput2, ex
35802
36630
  }
35803
36631
  let span;
35804
36632
  try {
35805
- const { input, metadata } = extractInput2(args);
36633
+ const { input, metadata } = extractInput3(args);
35806
36634
  span = startSpan(
35807
36635
  withSpanInstrumentationName(
35808
36636
  {
@@ -36578,6 +37406,7 @@ var BraintrustPlugin = class extends BasePlugin {
36578
37406
  cloudflareThinkPlugin = null;
36579
37407
  cursorSDKPlugin = null;
36580
37408
  openAIAgentsPlugin = null;
37409
+ googleGenerativeAIPlugin = null;
36581
37410
  googleGenAIPlugin = null;
36582
37411
  huggingFacePlugin = null;
36583
37412
  huggingFaceTransformersPlugin = null;
@@ -36596,6 +37425,7 @@ var BraintrustPlugin = class extends BasePlugin {
36596
37425
  langSmithPlugin = null;
36597
37426
  piCodingAgentPlugin = null;
36598
37427
  strandsAgentSDKPlugin = null;
37428
+ elevenLabsPlugin = null;
36599
37429
  voyageAIPlugin = null;
36600
37430
  cloudflareAIChatPlugin = null;
36601
37431
  cloudflareAgentsPlugin = null;
@@ -36637,6 +37467,10 @@ var BraintrustPlugin = class extends BasePlugin {
36637
37467
  this.openAIAgentsPlugin = new OpenAIAgentsPlugin();
36638
37468
  this.openAIAgentsPlugin.enable();
36639
37469
  }
37470
+ if (integrations.googleGenerativeAI !== false) {
37471
+ this.googleGenerativeAIPlugin = new GoogleGenerativeAIPlugin();
37472
+ this.googleGenerativeAIPlugin.enable();
37473
+ }
36640
37474
  if (integrations.googleGenAI !== false && integrations.google !== false) {
36641
37475
  this.googleGenAIPlugin = new GoogleGenAIPlugin();
36642
37476
  this.googleGenAIPlugin.enable();
@@ -36671,6 +37505,10 @@ var BraintrustPlugin = class extends BasePlugin {
36671
37505
  this.coherePlugin = new CoherePlugin();
36672
37506
  this.coherePlugin.enable();
36673
37507
  }
37508
+ if (integrations.elevenlabs !== false) {
37509
+ this.elevenLabsPlugin = new ElevenLabsPlugin();
37510
+ this.elevenLabsPlugin.enable();
37511
+ }
36674
37512
  if (integrations.voyageai !== false) {
36675
37513
  this.voyageAIPlugin = new VoyageAIPlugin();
36676
37514
  this.voyageAIPlugin.enable();
@@ -36755,6 +37593,10 @@ var BraintrustPlugin = class extends BasePlugin {
36755
37593
  this.openAIAgentsPlugin.disable();
36756
37594
  this.openAIAgentsPlugin = null;
36757
37595
  }
37596
+ if (this.googleGenerativeAIPlugin) {
37597
+ this.googleGenerativeAIPlugin.disable();
37598
+ this.googleGenerativeAIPlugin = null;
37599
+ }
36758
37600
  if (this.googleGenAIPlugin) {
36759
37601
  this.googleGenAIPlugin.disable();
36760
37602
  this.googleGenAIPlugin = null;
@@ -36791,6 +37633,10 @@ var BraintrustPlugin = class extends BasePlugin {
36791
37633
  this.coherePlugin.disable();
36792
37634
  this.coherePlugin = null;
36793
37635
  }
37636
+ if (this.elevenLabsPlugin) {
37637
+ this.elevenLabsPlugin.disable();
37638
+ this.elevenLabsPlugin = null;
37639
+ }
36794
37640
  if (this.voyageAIPlugin) {
36795
37641
  this.voyageAIPlugin.disable();
36796
37642
  this.voyageAIPlugin = null;
@@ -36884,6 +37730,8 @@ var envIntegrationAliases = {
36884
37730
  "openai-agents-core": "openAIAgents",
36885
37731
  openaiagentscore: "openAIAgents",
36886
37732
  google: "google",
37733
+ "google-generative-ai": "googleGenerativeAI",
37734
+ googlegenerativeai: "googleGenerativeAI",
36887
37735
  "google-genai": "googleGenAI",
36888
37736
  googlegenai: "googleGenAI",
36889
37737
  huggingface: "huggingface",
@@ -36917,7 +37765,9 @@ var envIntegrationAliases = {
36917
37765
  langsmith: "langsmith",
36918
37766
  voyage: "voyageai",
36919
37767
  "voyage-ai": "voyageai",
36920
- voyageai: "voyageai"
37768
+ voyageai: "voyageai",
37769
+ elevenlabs: "elevenlabs",
37770
+ "@elevenlabs/elevenlabs-js": "elevenlabs"
36921
37771
  };
36922
37772
  function getDefaultInstrumentationIntegrations() {
36923
37773
  return {
@@ -36928,6 +37778,7 @@ function getDefaultInstrumentationIntegrations() {
36928
37778
  aisdk: true,
36929
37779
  google: true,
36930
37780
  googleGenAI: true,
37781
+ googleGenerativeAI: true,
36931
37782
  googleADK: true,
36932
37783
  huggingface: true,
36933
37784
  claudeAgentSDK: true,
@@ -36953,6 +37804,7 @@ function getDefaultInstrumentationIntegrations() {
36953
37804
  langgraph: true,
36954
37805
  langsmith: true,
36955
37806
  voyageai: true,
37807
+ elevenlabs: true,
36956
37808
  piCodingAgent: true,
36957
37809
  strandsAgentSDK: true,
36958
37810
  cloudflareAgents: true