braintrust 3.30.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 +740 -1
  2. package/dev/dist/index.d.ts +740 -1
  3. package/dev/dist/index.js +1307 -434
  4. package/dev/dist/index.mjs +886 -13
  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 +113 -5
  10. package/dist/auto-instrumentations/bundler/next.mjs +12 -6
  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 +126 -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 +3052 -927
  27. package/dist/browser.d.ts +3052 -927
  28. package/dist/browser.js +1023 -18
  29. package/dist/browser.mjs +1023 -18
  30. package/dist/{chunk-BU6SM54N.mjs → chunk-4QSAHP7D.mjs} +834 -10
  31. package/dist/{chunk-2XDW3UCG.js → chunk-AW4QECG5.js} +47 -4
  32. package/dist/{chunk-TWCDSYJN.js → chunk-BTRLPQG5.js} +1679 -855
  33. package/dist/{chunk-N3JKQ3D3.mjs → chunk-WV6QZI2W.mjs} +46 -3
  34. package/dist/cli.js +950 -14
  35. package/dist/edge-light.d.mts +1 -1
  36. package/dist/edge-light.d.ts +1 -1
  37. package/dist/edge-light.js +1023 -18
  38. package/dist/edge-light.mjs +1023 -18
  39. package/dist/index.d.mts +3052 -927
  40. package/dist/index.d.ts +3052 -927
  41. package/dist/index.js +594 -450
  42. package/dist/index.mjs +149 -5
  43. package/dist/instrumentation/index.d.mts +434 -0
  44. package/dist/instrumentation/index.d.ts +434 -0
  45. package/dist/instrumentation/index.js +875 -12
  46. package/dist/instrumentation/index.mjs +875 -12
  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 +1023 -18
  52. package/dist/workerd.mjs +1023 -18
  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-N3JKQ3D3.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({
@@ -3016,6 +3027,7 @@ var ProjectSettings = z6.union([
3016
3027
  ]),
3017
3028
  disable_realtime_queries: z6.union([z6.boolean(), z6.null()]),
3018
3029
  monitor_charts_use_metrics_start: z6.union([z6.boolean(), z6.null()]),
3030
+ blind_reviews: z6.union([z6.boolean(), z6.null()]),
3019
3031
  default_preprocessor: NullableSavedFunctionId
3020
3032
  }).partial(),
3021
3033
  z6.null()
@@ -3077,6 +3089,7 @@ var WindowedAutomationConfig = z6.object({
3077
3089
  auto_approve_tools: z6.array(z6.string().min(1)).optional().default([]),
3078
3090
  harness: z6.enum(["native", "codex", "claude-code"]).optional(),
3079
3091
  model: z6.string().min(1).optional(),
3092
+ endpoint_name: z6.string().min(1).optional(),
3080
3093
  reasoning_effort: z6.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]).optional()
3081
3094
  }).optional(),
3082
3095
  actions: z6.array(
@@ -10741,6 +10754,16 @@ function renderMessageImpl(render, message, variables) {
10741
10754
  }
10742
10755
  }
10743
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
+ ];
10744
10767
  case "file":
10745
10768
  return [
10746
10769
  {
@@ -14987,6 +15010,12 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14987
15010
  if (!activeEntry) {
14988
15011
  return result;
14989
15012
  }
15013
+ const executionOptions = args[1];
15014
+ const toolCallId = isObject(executionOptions) ? executionOptions.toolCallId : void 0;
15015
+ const toolInput = {
15016
+ input: serializeToolExecutionInput(args),
15017
+ ...typeof toolCallId === "string" ? { metadata: { toolCallId } } : {}
15018
+ };
14990
15019
  if (isAsyncGenerator(result)) {
14991
15020
  return (async function* () {
14992
15021
  const span = activeEntry.parentSpan.startSpan(
@@ -15000,7 +15029,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15000
15029
  INSTRUMENTATION_NAMES.AI_SDK
15001
15030
  )
15002
15031
  );
15003
- span.log({ input: serializeToolExecutionInput(args) });
15032
+ span.log(toolInput);
15004
15033
  try {
15005
15034
  let lastValue;
15006
15035
  for await (const value of result) {
@@ -15018,7 +15047,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
15018
15047
  }
15019
15048
  return activeEntry.parentSpan.traced(
15020
15049
  async (span) => {
15021
- span.log({ input: serializeToolExecutionInput(args) });
15050
+ span.log(toolInput);
15022
15051
  const awaitedResult = await result;
15023
15052
  span.log({ output: awaitedResult });
15024
15053
  return awaitedResult;
@@ -18572,14 +18601,17 @@ function getMetricsFromResponse(response) {
18572
18601
  if (!isRecord(usageMetadata)) {
18573
18602
  continue;
18574
18603
  }
18575
- const inputTokenDetails = usageMetadata.input_token_details;
18604
+ const inputTokenDetails = isRecord(usageMetadata.input_token_details) ? usageMetadata.input_token_details : {};
18576
18605
  const outputTokenDetails = usageMetadata.output_token_details;
18577
18606
  return normalizeTokenMetrics({
18578
18607
  total_tokens: usageMetadata.total_tokens,
18579
18608
  prompt_tokens: usageMetadata.input_tokens,
18580
18609
  completion_tokens: usageMetadata.output_tokens,
18581
- prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
18582
- prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0,
18610
+ // Prefer TTL-specific cache writes over the aggregate when available.
18611
+ prompt_cache_creation_tokens: inputTokenDetails.ephemeral_5m_input_tokens == null && inputTokenDetails.ephemeral_1h_input_tokens == null ? inputTokenDetails.cache_creation : void 0,
18612
+ prompt_cache_creation_5m_tokens: inputTokenDetails.ephemeral_5m_input_tokens,
18613
+ prompt_cache_creation_1h_tokens: inputTokenDetails.ephemeral_1h_input_tokens,
18614
+ prompt_cached_tokens: inputTokenDetails.cache_read,
18583
18615
  completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
18584
18616
  });
18585
18617
  }
@@ -24551,6 +24583,328 @@ var OpenAIAgentsPlugin = class extends BasePlugin {
24551
24583
  }
24552
24584
  };
24553
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
+
24554
24908
  // src/instrumentation/plugins/google-genai-plugin.ts
24555
24909
  var GOOGLE_GENAI_INTERNAL_CONTEXT = {
24556
24910
  caller_filename: "<node-internal>",
@@ -26102,7 +26456,7 @@ var HuggingFaceTransformersPlugin = class extends BasePlugin {
26102
26456
  getTask(event)
26103
26457
  ),
26104
26458
  extractInput: (args, event) => ({
26105
- input: extractInput(
26459
+ input: extractInput2(
26106
26460
  getTask(event),
26107
26461
  args
26108
26462
  ),
@@ -26192,7 +26546,7 @@ function modelIdentifier(pipeline) {
26192
26546
  }
26193
26547
  return void 0;
26194
26548
  }
26195
- function extractInput(task, args) {
26549
+ function extractInput2(task, args) {
26196
26550
  switch (task) {
26197
26551
  case "feature-extraction":
26198
26552
  return args[0];
@@ -34627,6 +34981,458 @@ function logInstrumentationError5(context, error) {
34627
34981
  debugLogger.debug(`${context}:`, error);
34628
34982
  }
34629
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
+
34630
35436
  // src/instrumentation/plugins/voyageai-plugin.ts
34631
35437
  var RERANK_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
34632
35438
  "model",
@@ -34670,7 +35476,7 @@ var VoyageAIPlugin = class extends BasePlugin {
34670
35476
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
34671
35477
  }
34672
35478
  };
34673
- function interceptVoyageAICall(channel, name, extractInput2, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
35479
+ function interceptVoyageAICall(channel, name, extractInput3, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
34674
35480
  return channel.intercept((target, thisArg, args) => {
34675
35481
  const invokeTarget = () => Reflect.apply(target, thisArg, args);
34676
35482
  if (isAutoInstrumentationSuppressed()) {
@@ -34678,7 +35484,7 @@ function interceptVoyageAICall(channel, name, extractInput2, extractOutput2, ext
34678
35484
  }
34679
35485
  let span;
34680
35486
  try {
34681
- const { input, metadata } = extractInput2(args);
35487
+ const { input, metadata } = extractInput3(args);
34682
35488
  span = startSpan(
34683
35489
  withSpanInstrumentationName(
34684
35490
  {
@@ -35449,6 +36255,7 @@ var BraintrustPlugin = class extends BasePlugin {
35449
36255
  cloudflareThinkPlugin = null;
35450
36256
  cursorSDKPlugin = null;
35451
36257
  openAIAgentsPlugin = null;
36258
+ googleGenerativeAIPlugin = null;
35452
36259
  googleGenAIPlugin = null;
35453
36260
  huggingFacePlugin = null;
35454
36261
  huggingFaceTransformersPlugin = null;
@@ -35467,6 +36274,7 @@ var BraintrustPlugin = class extends BasePlugin {
35467
36274
  langSmithPlugin = null;
35468
36275
  piCodingAgentPlugin = null;
35469
36276
  strandsAgentSDKPlugin = null;
36277
+ elevenLabsPlugin = null;
35470
36278
  voyageAIPlugin = null;
35471
36279
  cloudflareAIChatPlugin = null;
35472
36280
  cloudflareAgentsPlugin = null;
@@ -35508,6 +36316,10 @@ var BraintrustPlugin = class extends BasePlugin {
35508
36316
  this.openAIAgentsPlugin = new OpenAIAgentsPlugin();
35509
36317
  this.openAIAgentsPlugin.enable();
35510
36318
  }
36319
+ if (integrations.googleGenerativeAI !== false) {
36320
+ this.googleGenerativeAIPlugin = new GoogleGenerativeAIPlugin();
36321
+ this.googleGenerativeAIPlugin.enable();
36322
+ }
35511
36323
  if (integrations.googleGenAI !== false && integrations.google !== false) {
35512
36324
  this.googleGenAIPlugin = new GoogleGenAIPlugin();
35513
36325
  this.googleGenAIPlugin.enable();
@@ -35542,6 +36354,10 @@ var BraintrustPlugin = class extends BasePlugin {
35542
36354
  this.coherePlugin = new CoherePlugin();
35543
36355
  this.coherePlugin.enable();
35544
36356
  }
36357
+ if (integrations.elevenlabs !== false) {
36358
+ this.elevenLabsPlugin = new ElevenLabsPlugin();
36359
+ this.elevenLabsPlugin.enable();
36360
+ }
35545
36361
  if (integrations.voyageai !== false) {
35546
36362
  this.voyageAIPlugin = new VoyageAIPlugin();
35547
36363
  this.voyageAIPlugin.enable();
@@ -35626,6 +36442,10 @@ var BraintrustPlugin = class extends BasePlugin {
35626
36442
  this.openAIAgentsPlugin.disable();
35627
36443
  this.openAIAgentsPlugin = null;
35628
36444
  }
36445
+ if (this.googleGenerativeAIPlugin) {
36446
+ this.googleGenerativeAIPlugin.disable();
36447
+ this.googleGenerativeAIPlugin = null;
36448
+ }
35629
36449
  if (this.googleGenAIPlugin) {
35630
36450
  this.googleGenAIPlugin.disable();
35631
36451
  this.googleGenAIPlugin = null;
@@ -35662,6 +36482,10 @@ var BraintrustPlugin = class extends BasePlugin {
35662
36482
  this.coherePlugin.disable();
35663
36483
  this.coherePlugin = null;
35664
36484
  }
36485
+ if (this.elevenLabsPlugin) {
36486
+ this.elevenLabsPlugin.disable();
36487
+ this.elevenLabsPlugin = null;
36488
+ }
35665
36489
  if (this.voyageAIPlugin) {
35666
36490
  this.voyageAIPlugin.disable();
35667
36491
  this.voyageAIPlugin = null;