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
package/dist/browser.mjs CHANGED
@@ -2815,6 +2815,14 @@ var ChatCompletionContentPartImageWithTitle = z6.object({
2815
2815
  ttl: z6.enum(["5m", "1h"]).optional()
2816
2816
  }).optional()
2817
2817
  });
2818
+ var ChatCompletionContentPartInputAudioWithTitle = z6.object({
2819
+ input_audio: z6.object({ data: z6.string(), format: z6.enum(["wav", "mp3"]) }),
2820
+ type: z6.literal("input_audio"),
2821
+ cache_control: z6.object({
2822
+ type: z6.literal("ephemeral"),
2823
+ ttl: z6.enum(["5m", "1h"]).optional()
2824
+ }).optional()
2825
+ });
2818
2826
  var ChatCompletionContentPartFileFile = z6.object({ file_data: z6.string(), filename: z6.string(), file_id: z6.string() }).partial();
2819
2827
  var ChatCompletionContentPartFileWithTitle = z6.object({
2820
2828
  file: ChatCompletionContentPartFileFile,
@@ -2827,6 +2835,7 @@ var ChatCompletionContentPartFileWithTitle = z6.object({
2827
2835
  var ChatCompletionContentPart = z6.union([
2828
2836
  ChatCompletionContentPartTextWithTitle,
2829
2837
  ChatCompletionContentPartImageWithTitle,
2838
+ ChatCompletionContentPartInputAudioWithTitle,
2830
2839
  ChatCompletionContentPartFileWithTitle
2831
2840
  ]);
2832
2841
  var ChatCompletionContentPartText = z6.object({
@@ -3818,6 +3827,7 @@ var ProjectSettings = z6.union([
3818
3827
  ]),
3819
3828
  disable_realtime_queries: z6.union([z6.boolean(), z6.null()]),
3820
3829
  monitor_charts_use_metrics_start: z6.union([z6.boolean(), z6.null()]),
3830
+ blind_reviews: z6.union([z6.boolean(), z6.null()]),
3821
3831
  default_preprocessor: NullableSavedFunctionId
3822
3832
  }).partial(),
3823
3833
  z6.null()
@@ -3879,6 +3889,7 @@ var WindowedAutomationConfig = z6.object({
3879
3889
  auto_approve_tools: z6.array(z6.string().min(1)).optional().default([]),
3880
3890
  harness: z6.enum(["native", "codex", "claude-code"]).optional(),
3881
3891
  model: z6.string().min(1).optional(),
3892
+ endpoint_name: z6.string().min(1).optional(),
3882
3893
  reasoning_effort: z6.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]).optional()
3883
3894
  }).optional(),
3884
3895
  actions: z6.array(
@@ -5652,6 +5663,7 @@ var INSTRUMENTATION_NAMES = {
5652
5663
  GENKIT: "genkit",
5653
5664
  GITHUB_COPILOT: "github-copilot",
5654
5665
  GOOGLE_ADK: "google-adk",
5666
+ GOOGLE_GENERATIVE_AI: "google-generative-ai",
5655
5667
  GOOGLE_GENAI: "google-genai",
5656
5668
  GROQ: "groq",
5657
5669
  HUGGINGFACE: "huggingface",
@@ -5667,12 +5679,13 @@ var INSTRUMENTATION_NAMES = {
5667
5679
  OPENROUTER_AGENT: "openrouter-agent",
5668
5680
  PI_CODING_AGENT: "pi-coding-agent",
5669
5681
  STRANDS_AGENT_SDK: "strands-agent-sdk",
5670
- VOYAGEAI: "voyageai"
5682
+ VOYAGEAI: "voyageai",
5683
+ ELEVENLABS: "elevenlabs"
5671
5684
  };
5672
5685
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5673
5686
  "braintrust.spanInstrumentationName"
5674
5687
  );
5675
- var SDK_VERSION = true ? "3.30.0" : "0.0.0";
5688
+ var SDK_VERSION = true ? "3.32.0" : "0.0.0";
5676
5689
  function withSpanInstrumentationName(args, instrumentationName) {
5677
5690
  return {
5678
5691
  ...args,
@@ -11630,6 +11643,16 @@ function renderMessageImpl(render, message, variables) {
11630
11643
  }
11631
11644
  }
11632
11645
  ];
11646
+ case "input_audio":
11647
+ return [
11648
+ {
11649
+ ...c,
11650
+ input_audio: {
11651
+ ...c.input_audio,
11652
+ data: render(c.input_audio.data)
11653
+ }
11654
+ }
11655
+ ];
11633
11656
  case "file":
11634
11657
  return [
11635
11658
  {
@@ -19789,6 +19812,12 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
19789
19812
  if (!activeEntry) {
19790
19813
  return result;
19791
19814
  }
19815
+ const executionOptions = args[1];
19816
+ const toolCallId = isObject(executionOptions) ? executionOptions.toolCallId : void 0;
19817
+ const toolInput = {
19818
+ input: serializeToolExecutionInput(args),
19819
+ ...typeof toolCallId === "string" ? { metadata: { toolCallId } } : {}
19820
+ };
19792
19821
  if (isAsyncGenerator(result)) {
19793
19822
  return (async function* () {
19794
19823
  const span = activeEntry.parentSpan.startSpan(
@@ -19802,7 +19831,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
19802
19831
  INSTRUMENTATION_NAMES.AI_SDK
19803
19832
  )
19804
19833
  );
19805
- span.log({ input: serializeToolExecutionInput(args) });
19834
+ span.log(toolInput);
19806
19835
  try {
19807
19836
  let lastValue;
19808
19837
  for await (const value of result) {
@@ -19820,7 +19849,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
19820
19849
  }
19821
19850
  return activeEntry.parentSpan.traced(
19822
19851
  async (span) => {
19823
- span.log({ input: serializeToolExecutionInput(args) });
19852
+ span.log(toolInput);
19824
19853
  const awaitedResult = await result;
19825
19854
  span.log({ output: awaitedResult });
19826
19855
  return awaitedResult;
@@ -24224,6 +24253,342 @@ var OpenAIAgentsPlugin = class extends BasePlugin {
24224
24253
  }
24225
24254
  };
24226
24255
 
24256
+ // src/instrumentation/plugins/google-generative-ai-channels.ts
24257
+ var googleGenerativeAIChannels = defineChannels(
24258
+ "@google/generative-ai",
24259
+ {
24260
+ generateContent: channel({ channelName: "GenerativeModel.generateContent", kind: "async" }),
24261
+ generateContentStream: channel({ channelName: "GenerativeModel.generateContentStream", kind: "async" }),
24262
+ embedContent: channel({ channelName: "GenerativeModel.embedContent", kind: "async" }),
24263
+ batchEmbedContents: channel({ channelName: "GenerativeModel.batchEmbedContents", kind: "async" }),
24264
+ sendMessage: channel({ channelName: "ChatSession.sendMessage", kind: "async" }),
24265
+ sendMessageStream: channel({ channelName: "ChatSession.sendMessageStream", kind: "async" })
24266
+ },
24267
+ { instrumentationName: INSTRUMENTATION_NAMES.GOOGLE_GENERATIVE_AI }
24268
+ );
24269
+
24270
+ // src/instrumentation/plugins/google-generative-ai-plugin.ts
24271
+ var GENERATION_CONFIG_KEYS = [
24272
+ "temperature",
24273
+ "topP",
24274
+ "topK",
24275
+ "candidateCount",
24276
+ "maxOutputTokens",
24277
+ "stopSequences",
24278
+ "responseMimeType",
24279
+ "responseSchema",
24280
+ "presencePenalty",
24281
+ "frequencyPenalty",
24282
+ "responseLogprobs",
24283
+ "logprobs",
24284
+ "thinkingConfig"
24285
+ ];
24286
+ var GoogleGenerativeAIPlugin = class extends BasePlugin {
24287
+ onEnable() {
24288
+ this.unsubscribers.push(
24289
+ interceptCall(
24290
+ googleGenerativeAIChannels.generateContent,
24291
+ "generateContent"
24292
+ ),
24293
+ interceptCall(
24294
+ googleGenerativeAIChannels.generateContentStream,
24295
+ "generateContentStream"
24296
+ ),
24297
+ interceptCall(googleGenerativeAIChannels.sendMessage, "sendMessage"),
24298
+ interceptCall(
24299
+ googleGenerativeAIChannels.sendMessageStream,
24300
+ "sendMessageStream"
24301
+ ),
24302
+ interceptCall(googleGenerativeAIChannels.embedContent, "embedContent"),
24303
+ interceptCall(
24304
+ googleGenerativeAIChannels.batchEmbedContents,
24305
+ "batchEmbedContents"
24306
+ )
24307
+ );
24308
+ }
24309
+ onDisable() {
24310
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
24311
+ }
24312
+ };
24313
+ function interceptCall(channel2, operation) {
24314
+ return channel2.intercept((target, thisArg, args) => {
24315
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
24316
+ if (isAutoInstrumentationSuppressed()) return invokeTarget();
24317
+ const self = thisArg;
24318
+ const chat = operation.startsWith("sendMessage");
24319
+ const embedding = operation === "embedContent" || operation === "batchEmbedContents";
24320
+ const start = getCurrentUnixTimestamp();
24321
+ let span;
24322
+ try {
24323
+ span = startSpan(
24324
+ withSpanInstrumentationName(
24325
+ {
24326
+ name: embedding ? operation === "embedContent" ? "embed_content" : "batch_embed_contents" : "generate_content",
24327
+ spanAttributes: { type: "llm" /* LLM */ },
24328
+ event: extractInput(self, args[0], operation)
24329
+ },
24330
+ INSTRUMENTATION_NAMES.GOOGLE_GENERATIVE_AI
24331
+ )
24332
+ );
24333
+ } catch (error) {
24334
+ debugLogger.error("Error starting Google Generative AI span:", error);
24335
+ return invokeTarget();
24336
+ }
24337
+ let ended = false;
24338
+ const finish = (log3) => {
24339
+ if (ended) return;
24340
+ ended = true;
24341
+ try {
24342
+ log3();
24343
+ } catch (error) {
24344
+ debugLogger.error("Error logging Google Generative AI span:", error);
24345
+ }
24346
+ try {
24347
+ span.end();
24348
+ } catch (error) {
24349
+ debugLogger.error("Error ending Google Generative AI span:", error);
24350
+ }
24351
+ };
24352
+ if (chat) {
24353
+ try {
24354
+ void self._sendPromise.then(
24355
+ () => {
24356
+ try {
24357
+ span.log(extractInput(self, args[0], operation));
24358
+ } catch (error) {
24359
+ debugLogger.error("Error capturing Google chat history:", error);
24360
+ }
24361
+ },
24362
+ () => {
24363
+ }
24364
+ );
24365
+ } catch (error) {
24366
+ debugLogger.error("Error observing Google chat history:", error);
24367
+ }
24368
+ }
24369
+ let result;
24370
+ try {
24371
+ result = withCurrent(
24372
+ span,
24373
+ () => runWithAutoInstrumentationSuppressed(invokeTarget)
24374
+ );
24375
+ } catch (error) {
24376
+ finish(() => span.log({ error }));
24377
+ throw error;
24378
+ }
24379
+ void Promise.resolve(result).then(
24380
+ (value) => {
24381
+ try {
24382
+ if ("stream" in value) {
24383
+ let firstToken = false;
24384
+ const partial = { candidates: [] };
24385
+ const candidates = /* @__PURE__ */ new Map();
24386
+ patchStreamIfNeeded(value.stream, {
24387
+ aroundNext: (callback) => withCurrent(span, callback),
24388
+ onChunk: (chunk) => {
24389
+ for (const candidate of chunk.candidates ?? []) {
24390
+ const index = candidate.index ?? 0;
24391
+ const previous = candidates.get(index);
24392
+ const parts = [...previous?.content?.parts ?? []];
24393
+ for (const part of candidate.content?.parts ?? []) {
24394
+ const last = parts[parts.length - 1];
24395
+ if (part.text !== void 0 && last?.text !== void 0) {
24396
+ parts[parts.length - 1] = {
24397
+ ...last,
24398
+ text: last.text + part.text
24399
+ };
24400
+ } else parts.push(part);
24401
+ }
24402
+ candidates.set(index, {
24403
+ ...previous,
24404
+ ...candidate,
24405
+ content: {
24406
+ role: candidate.content?.role ?? previous?.content?.role ?? "model",
24407
+ parts
24408
+ }
24409
+ });
24410
+ }
24411
+ partial.candidates = Array.from(candidates.values());
24412
+ if (chunk.usageMetadata)
24413
+ partial.usageMetadata = chunk.usageMetadata;
24414
+ if (!firstToken && chunk.candidates?.some(
24415
+ (candidate) => candidate.content?.parts.some(
24416
+ (part) => part.text !== void 0 ? part.text.length > 0 : Object.keys(part).length > 0
24417
+ )
24418
+ )) {
24419
+ firstToken = true;
24420
+ span.log({
24421
+ metrics: {
24422
+ time_to_first_token: getCurrentUnixTimestamp() - start
24423
+ }
24424
+ });
24425
+ }
24426
+ },
24427
+ onComplete: () => {
24428
+ },
24429
+ onError: (error) => finish(() => {
24430
+ logResponse(span, partial);
24431
+ span.log({ error });
24432
+ }),
24433
+ onCancel: () => finish(() => logResponse(span, partial))
24434
+ });
24435
+ void value.response.then(
24436
+ (response) => finish(() => logResponse(span, response)),
24437
+ (error) => finish(() => {
24438
+ logResponse(span, partial);
24439
+ span.log({ error });
24440
+ })
24441
+ );
24442
+ } else if ("response" in value) {
24443
+ finish(() => logResponse(span, value.response));
24444
+ } else {
24445
+ const metrics = {};
24446
+ const promptTokens = value.usageMetadata?.promptTokenCount;
24447
+ if (typeof promptTokens === "number" && Number.isFinite(promptTokens) && promptTokens >= 0) {
24448
+ metrics.prompt_tokens = promptTokens;
24449
+ metrics.tokens = promptTokens;
24450
+ }
24451
+ for (const detail of value.usageMetadata?.promptTokenDetails ?? []) {
24452
+ if (detail.modality === "AUDIO" && typeof detail.tokenCount === "number" && Number.isFinite(detail.tokenCount) && detail.tokenCount >= 0) {
24453
+ metrics.prompt_audio_tokens = (metrics.prompt_audio_tokens ?? 0) + detail.tokenCount;
24454
+ }
24455
+ }
24456
+ finish(
24457
+ () => span.log({
24458
+ metrics,
24459
+ output: {
24460
+ count: value.embeddings?.length ?? (value.embedding ? 1 : 0)
24461
+ }
24462
+ })
24463
+ );
24464
+ }
24465
+ } catch (error) {
24466
+ debugLogger.error(
24467
+ "Error observing Google Generative AI result:",
24468
+ error
24469
+ );
24470
+ finish(() => {
24471
+ });
24472
+ }
24473
+ },
24474
+ (error) => finish(() => span.log({ error }))
24475
+ );
24476
+ return result;
24477
+ });
24478
+ }
24479
+ function normalizeContent(message) {
24480
+ const parts = (typeof message === "string" ? [message] : message).map(
24481
+ (part) => typeof part === "string" ? { text: part } : part
24482
+ );
24483
+ return {
24484
+ role: parts.some((part) => part.functionResponse) ? "function" : "user",
24485
+ parts
24486
+ };
24487
+ }
24488
+ function extractInput(self, request, operation) {
24489
+ const model = self.model.replace(/^models\//, "");
24490
+ if (operation === "embedContent" || operation === "batchEmbedContents") {
24491
+ const requests = operation === "batchEmbedContents" ? request.requests : [
24492
+ typeof request === "string" || Array.isArray(request) ? { content: normalizeContent(request) } : request
24493
+ ];
24494
+ const dimensions = requests[0]?.outputDimensionality;
24495
+ return {
24496
+ input: {
24497
+ inputs: convertAttachments(requests).map((item) => ({
24498
+ content: item.content.parts.length === 1 && item.content.parts[0].text !== void 0 ? item.content.parts[0].text : item.content.parts.map((part) => {
24499
+ if (part.text !== void 0)
24500
+ return { type: "text", text: part.text };
24501
+ const mimeType = part.inlineData?.mimeType ?? part.fileData?.mimeType;
24502
+ const data = part.inlineData ? typeof part.inlineData.data === "string" ? `data:${mimeType};base64,${part.inlineData.data}` : part.inlineData.data : part.fileData?.fileUri;
24503
+ return mimeType?.startsWith("image/") ? { type: "image_url", image_url: { url: data } } : { type: "file", file: { file_data: data } };
24504
+ })
24505
+ })),
24506
+ ...dimensions !== void 0 && requests.every((item) => item.outputDimensionality === dimensions) ? { output_dimensions: dimensions } : {}
24507
+ },
24508
+ metadata: { model, provider: "google" }
24509
+ };
24510
+ }
24511
+ const chat = operation.startsWith("sendMessage");
24512
+ const config = chat ? self.params ?? {} : self;
24513
+ const params = typeof request === "string" || Array.isArray(request) ? { contents: [normalizeContent(request)] } : request;
24514
+ const system = params.systemInstruction ?? config.systemInstruction;
24515
+ const systemContent = typeof system === "string" ? { role: "system", parts: [{ text: system }] } : system && "parts" in system ? { ...system, role: "system" } : system ? { role: "system", parts: [system] } : void 0;
24516
+ const contents = [
24517
+ ...systemContent ? [systemContent] : [],
24518
+ ...chat ? self._history : [],
24519
+ ...params.contents
24520
+ ];
24521
+ const metadata = { model, provider: "google" };
24522
+ const generation = params.generationConfig ?? config.generationConfig;
24523
+ for (const key of GENERATION_CONFIG_KEYS) {
24524
+ if (generation && Object.hasOwn(generation, key))
24525
+ metadata[key] = generation[key];
24526
+ }
24527
+ for (const key of ["tools", "toolConfig", "safetySettings"]) {
24528
+ const value = params[key] ?? config[key];
24529
+ if (value !== void 0) metadata[key] = value;
24530
+ }
24531
+ const cached = params.cachedContent ?? config.cachedContent;
24532
+ if (cached)
24533
+ metadata.cachedContent = typeof cached === "string" ? cached : cached.name;
24534
+ return { input: convertAttachments({ model, contents }), metadata };
24535
+ }
24536
+ function convertAttachments(value) {
24537
+ const convert = (node) => {
24538
+ if (Array.isArray(node)) return node.map(convert);
24539
+ if (!isObject(node)) return node;
24540
+ if (isObject(node.inlineData)) {
24541
+ const { data, mimeType } = node.inlineData;
24542
+ const processed = processInputAttachments({
24543
+ type: "file",
24544
+ file: { file_data: `data:${mimeType};base64,${data}` }
24545
+ });
24546
+ if (typeof processed.file.file_data === "string")
24547
+ throw new Error("Unable to convert Google inline data");
24548
+ return {
24549
+ ...node,
24550
+ inlineData: { ...node.inlineData, data: processed.file.file_data }
24551
+ };
24552
+ }
24553
+ return Object.fromEntries(
24554
+ Object.entries(node).map(([key, item]) => [key, convert(item)])
24555
+ );
24556
+ };
24557
+ try {
24558
+ return convert(value);
24559
+ } catch (error) {
24560
+ debugLogger.error(
24561
+ "Error converting Google Generative AI attachments:",
24562
+ error
24563
+ );
24564
+ return value;
24565
+ }
24566
+ }
24567
+ function logResponse(span, response) {
24568
+ const usage = response.usageMetadata;
24569
+ const metrics = {};
24570
+ if (usage) {
24571
+ if (usage.promptTokenCount !== void 0)
24572
+ metrics.prompt_tokens = usage.promptTokenCount;
24573
+ if (usage.candidatesTokenCount !== void 0 || usage.thoughtsTokenCount !== void 0)
24574
+ metrics.completion_tokens = (usage.candidatesTokenCount ?? 0) + (usage.thoughtsTokenCount ?? 0);
24575
+ if (usage.totalTokenCount !== void 0)
24576
+ metrics.tokens = usage.totalTokenCount;
24577
+ if (usage.cachedContentTokenCount !== void 0)
24578
+ metrics.prompt_cached_tokens = usage.cachedContentTokenCount;
24579
+ if (usage.thoughtsTokenCount !== void 0)
24580
+ metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
24581
+ }
24582
+ span.log({
24583
+ output: convertAttachments({
24584
+ candidates: response.candidates,
24585
+ promptFeedback: response.promptFeedback
24586
+ }),
24587
+ metrics,
24588
+ ...response.modelVersion ? { metadata: { model: response.modelVersion } } : {}
24589
+ });
24590
+ }
24591
+
24227
24592
  // src/instrumentation/plugins/google-genai-channels.ts
24228
24593
  var googleGenAIChannels = defineChannels(
24229
24594
  "@google/genai",
@@ -25867,7 +26232,7 @@ var HuggingFaceTransformersPlugin = class extends BasePlugin {
25867
26232
  getTask(event)
25868
26233
  ),
25869
26234
  extractInput: (args, event) => ({
25870
- input: extractInput(
26235
+ input: extractInput2(
25871
26236
  getTask(event),
25872
26237
  args
25873
26238
  ),
@@ -25957,7 +26322,7 @@ function modelIdentifier(pipeline) {
25957
26322
  }
25958
26323
  return void 0;
25959
26324
  }
25960
- function extractInput(task, args) {
26325
+ function extractInput2(task, args) {
25961
26326
  switch (task) {
25962
26327
  case "feature-extraction":
25963
26328
  return args[0];
@@ -33942,14 +34307,17 @@ function getMetricsFromResponse(response) {
33942
34307
  if (!isRecord(usageMetadata)) {
33943
34308
  continue;
33944
34309
  }
33945
- const inputTokenDetails = usageMetadata.input_token_details;
34310
+ const inputTokenDetails = isRecord(usageMetadata.input_token_details) ? usageMetadata.input_token_details : {};
33946
34311
  const outputTokenDetails = usageMetadata.output_token_details;
33947
34312
  return normalizeTokenMetrics({
33948
34313
  total_tokens: usageMetadata.total_tokens,
33949
34314
  prompt_tokens: usageMetadata.input_tokens,
33950
34315
  completion_tokens: usageMetadata.output_tokens,
33951
- prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
33952
- prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0,
34316
+ // Prefer TTL-specific cache writes over the aggregate when available.
34317
+ prompt_cache_creation_tokens: inputTokenDetails.ephemeral_5m_input_tokens == null && inputTokenDetails.ephemeral_1h_input_tokens == null ? inputTokenDetails.cache_creation : void 0,
34318
+ prompt_cache_creation_5m_tokens: inputTokenDetails.ephemeral_5m_input_tokens,
34319
+ prompt_cache_creation_1h_tokens: inputTokenDetails.ephemeral_1h_input_tokens,
34320
+ prompt_cached_tokens: inputTokenDetails.cache_read,
33953
34321
  completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
33954
34322
  });
33955
34323
  }
@@ -36308,6 +36676,477 @@ function logInstrumentationError5(context, error) {
36308
36676
  debugLogger.debug(`${context}:`, error);
36309
36677
  }
36310
36678
 
36679
+ // src/instrumentation/plugins/elevenlabs-channels.ts
36680
+ var elevenLabsChannels = defineChannels(
36681
+ "@elevenlabs/elevenlabs-js",
36682
+ {
36683
+ convert: channel({
36684
+ channelName: "textToSpeech.convert",
36685
+ kind: "async"
36686
+ }),
36687
+ stream: channel({
36688
+ channelName: "textToSpeech.stream",
36689
+ kind: "async"
36690
+ }),
36691
+ convertWithTimestamps: channel({ channelName: "textToSpeech.convertWithTimestamps", kind: "async" }),
36692
+ streamWithTimestamps: channel({ channelName: "textToSpeech.streamWithTimestamps", kind: "async" }),
36693
+ transcribe: channel({ channelName: "speechToText.convert", kind: "async" })
36694
+ },
36695
+ { instrumentationName: INSTRUMENTATION_NAMES.ELEVENLABS }
36696
+ );
36697
+
36698
+ // src/instrumentation/plugins/elevenlabs-plugin.ts
36699
+ var ElevenLabsPlugin = class extends BasePlugin {
36700
+ onEnable() {
36701
+ for (const method of [
36702
+ "convert",
36703
+ "stream",
36704
+ "convertWithTimestamps",
36705
+ "streamWithTimestamps"
36706
+ ]) {
36707
+ this.unsubscribers.push(
36708
+ interceptCall2(
36709
+ elevenLabsChannels[method],
36710
+ `elevenlabs.textToSpeech.${method}`,
36711
+ ([voice, request]) => ({
36712
+ input: {
36713
+ operation: "speech",
36714
+ prompt: request.text,
36715
+ parameters: {
36716
+ voice,
36717
+ format: request.outputFormat,
36718
+ language: request.languageCode,
36719
+ speed: request.voiceSettings?.speed
36720
+ }
36721
+ },
36722
+ metadata: {
36723
+ provider: "elevenlabs",
36724
+ model: request.modelId ?? "eleven_multilingual_v2"
36725
+ }
36726
+ }),
36727
+ (value, args, span, finish, headers, started) => captureSpeech(
36728
+ value,
36729
+ args[1],
36730
+ method,
36731
+ span,
36732
+ finish,
36733
+ started,
36734
+ headers
36735
+ )
36736
+ )
36737
+ );
36738
+ }
36739
+ this.unsubscribers.push(
36740
+ interceptCall2(
36741
+ elevenLabsChannels.transcribe,
36742
+ "elevenlabs.speechToText.convert",
36743
+ ([request]) => {
36744
+ if (request.webhook) return void 0;
36745
+ const file = request.file;
36746
+ const filename = typeof File !== "undefined" && file instanceof File ? file.name : "audio";
36747
+ const contentType = file instanceof Blob ? file.type || "application/octet-stream" : "application/octet-stream";
36748
+ 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;
36749
+ const fileData = blob ? new Attachment({ data: blob, filename, contentType }) : request.cloudStorageUrl;
36750
+ return {
36751
+ input: {
36752
+ operation: "transcribe",
36753
+ content: fileData ? [{ type: "file", file: { filename, file_data: fileData } }] : [],
36754
+ parameters: {
36755
+ language: request.languageCode,
36756
+ timestamp_granularities: request.timestampsGranularity
36757
+ }
36758
+ },
36759
+ metadata: { provider: "elevenlabs", model: request.modelId }
36760
+ };
36761
+ },
36762
+ (value, _args, span, finish) => {
36763
+ const result = value;
36764
+ const transcripts = result.transcripts ?? [result];
36765
+ span.log({
36766
+ output: {
36767
+ content: transcripts.flatMap(
36768
+ (transcript) => typeof transcript.text === "string" ? [{ type: "text", text: transcript.text }] : []
36769
+ ),
36770
+ annotations: {
36771
+ language: result.languageCode,
36772
+ words: result.words ?? (result.transcripts ? result.transcripts.flatMap(
36773
+ (transcript) => transcript.words ?? []
36774
+ ) : void 0)
36775
+ }
36776
+ }
36777
+ });
36778
+ finish();
36779
+ },
36780
+ ([request], span) => {
36781
+ const file = request.file;
36782
+ if (!isAsyncIterable(file)) return;
36783
+ const chunks = [];
36784
+ const filename = isObject(file) && typeof file.path === "string" ? file.path.split(/[\\/]/).pop() || "audio" : "audio";
36785
+ observeAudioStream(
36786
+ file,
36787
+ (chunk) => chunks.push(new Uint8Array(chunk)),
36788
+ () => {
36789
+ const contentType = "application/octet-stream";
36790
+ const data = new Blob(chunks, {
36791
+ type: contentType
36792
+ });
36793
+ chunks.length = 0;
36794
+ span.log({
36795
+ input: {
36796
+ content: [
36797
+ {
36798
+ type: "file",
36799
+ file: {
36800
+ filename,
36801
+ file_data: new Attachment({
36802
+ data,
36803
+ filename,
36804
+ contentType
36805
+ })
36806
+ }
36807
+ }
36808
+ ]
36809
+ }
36810
+ });
36811
+ },
36812
+ () => {
36813
+ chunks.length = 0;
36814
+ },
36815
+ span
36816
+ );
36817
+ }
36818
+ )
36819
+ );
36820
+ }
36821
+ onDisable() {
36822
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
36823
+ }
36824
+ };
36825
+ function interceptCall2(channel2, name, input, output, beforeInvoke) {
36826
+ return channel2.intercept((target, self, args) => {
36827
+ const invoke2 = () => Reflect.apply(target, self, args);
36828
+ if (isAutoInstrumentationSuppressed()) return invoke2();
36829
+ const started = Date.now() / 1e3;
36830
+ let span;
36831
+ try {
36832
+ const event = input(args);
36833
+ if (event !== void 0)
36834
+ span = startSpan(
36835
+ withSpanInstrumentationName(
36836
+ {
36837
+ name,
36838
+ spanAttributes: { type: "llm" /* LLM */ },
36839
+ event
36840
+ },
36841
+ INSTRUMENTATION_NAMES.ELEVENLABS
36842
+ )
36843
+ );
36844
+ } catch (error) {
36845
+ debugLogger.error("Error starting ElevenLabs span", error);
36846
+ return invoke2();
36847
+ }
36848
+ if (!span) return invoke2();
36849
+ const activeSpan = span;
36850
+ let ended = false;
36851
+ const finish = (error) => {
36852
+ if (ended) return;
36853
+ ended = true;
36854
+ try {
36855
+ if (error !== void 0) activeSpan.log({ error });
36856
+ activeSpan.end();
36857
+ } catch (loggingError) {
36858
+ debugLogger.error("Error ending ElevenLabs span", loggingError);
36859
+ }
36860
+ };
36861
+ try {
36862
+ beforeInvoke?.(args, span);
36863
+ } catch (error) {
36864
+ debugLogger.error("Error observing ElevenLabs input", error);
36865
+ }
36866
+ let result;
36867
+ try {
36868
+ result = withCurrent(
36869
+ span,
36870
+ () => runWithAutoInstrumentationSuppressed(invoke2)
36871
+ );
36872
+ } catch (error) {
36873
+ finish(error);
36874
+ throw error;
36875
+ }
36876
+ const capture = (value, headers) => {
36877
+ try {
36878
+ output(value, args, span, finish, headers, started);
36879
+ } catch (error) {
36880
+ debugLogger.error("Error capturing ElevenLabs output", error);
36881
+ finish();
36882
+ }
36883
+ };
36884
+ try {
36885
+ if (isObject(result) && typeof result.withRawResponse === "function") {
36886
+ void result.withRawResponse().then(
36887
+ ({
36888
+ data,
36889
+ rawResponse
36890
+ }) => capture(data, rawResponse?.headers),
36891
+ finish
36892
+ );
36893
+ } else {
36894
+ void Promise.resolve(result).then((value) => capture(value), finish);
36895
+ }
36896
+ } catch (error) {
36897
+ debugLogger.error("Error observing ElevenLabs result", error);
36898
+ finish();
36899
+ }
36900
+ return result;
36901
+ });
36902
+ }
36903
+ function captureSpeech(value, request, method, span, finish, started, headers) {
36904
+ const format = request.outputFormat ?? "mp3_44100_128";
36905
+ 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;
36906
+ const headerType = headers?.get("content-type")?.split(";")[0];
36907
+ const contentType = headerType?.startsWith("audio/") ? headerType : formatType;
36908
+ const disposition = headers?.get("content-disposition");
36909
+ const headerFilename = disposition?.match(
36910
+ /filename="([^"]+)"|filename=([^;]+)/i
36911
+ );
36912
+ const filename = headerFilename?.[1] ?? headerFilename?.[2]?.trim() ?? `speech.${contentType ? getExtensionFromMediaType(contentType) : "bin"}`;
36913
+ const chunks = [];
36914
+ const alignments = [];
36915
+ let bytes = 0;
36916
+ let first = true;
36917
+ let stopped = false;
36918
+ const observe = (chunk) => {
36919
+ if (stopped || chunk.byteLength === 0) return;
36920
+ if (first && method.startsWith("stream")) {
36921
+ span.log({
36922
+ metrics: { time_to_first_token: Date.now() / 1e3 - started }
36923
+ });
36924
+ }
36925
+ first = false;
36926
+ chunks.push(new Uint8Array(chunk));
36927
+ bytes += chunk.byteLength;
36928
+ };
36929
+ const complete = () => {
36930
+ if (stopped) return;
36931
+ stopped = true;
36932
+ try {
36933
+ const content = [];
36934
+ if (contentType && bytes) {
36935
+ const data = new Uint8Array(bytes);
36936
+ let offset = 0;
36937
+ for (const chunk of chunks) {
36938
+ data.set(chunk, offset);
36939
+ offset += chunk.length;
36940
+ }
36941
+ content.push({
36942
+ type: "file",
36943
+ file: {
36944
+ filename,
36945
+ byte_size: bytes,
36946
+ file_data: new Attachment({
36947
+ data: new Blob([data], { type: contentType }),
36948
+ filename,
36949
+ contentType
36950
+ })
36951
+ }
36952
+ });
36953
+ }
36954
+ span.log({
36955
+ output: {
36956
+ content,
36957
+ ...alignments.length ? { annotations: alignments } : {}
36958
+ }
36959
+ });
36960
+ } finally {
36961
+ chunks.length = 0;
36962
+ finish();
36963
+ }
36964
+ };
36965
+ const cancel = (error) => {
36966
+ stopped = true;
36967
+ chunks.length = 0;
36968
+ finish(error);
36969
+ };
36970
+ const timestampChunk = (chunk) => {
36971
+ const binary = atob(chunk.audioBase64);
36972
+ observe(Uint8Array.from(binary, (character) => character.charCodeAt(0)));
36973
+ if (chunk.alignment || chunk.normalizedAlignment)
36974
+ alignments.push({
36975
+ alignment: chunk.alignment,
36976
+ normalized_alignment: chunk.normalizedAlignment
36977
+ });
36978
+ };
36979
+ if (method === "convertWithTimestamps") {
36980
+ timestampChunk(value);
36981
+ complete();
36982
+ } else if (method === "streamWithTimestamps") {
36983
+ patchStreamIfNeeded(value, {
36984
+ shouldCollect: (chunk) => {
36985
+ try {
36986
+ timestampChunk(chunk);
36987
+ } catch (error) {
36988
+ debugLogger.error("Error collecting ElevenLabs timestamps", error);
36989
+ cancel();
36990
+ }
36991
+ return false;
36992
+ },
36993
+ onComplete: complete,
36994
+ onCancel: () => cancel(),
36995
+ onError: cancel,
36996
+ aroundNext: (next) => withCurrent(span, next)
36997
+ });
36998
+ } else {
36999
+ observeAudioStream(value, observe, complete, cancel, span);
37000
+ }
37001
+ }
37002
+ function observeAudioStream(value, observe, complete, cancel, span) {
37003
+ let ended = false;
37004
+ const safeObserve = (chunk) => {
37005
+ if (ended) return;
37006
+ try {
37007
+ observe(chunk);
37008
+ } catch (error) {
37009
+ debugLogger.error("Error collecting ElevenLabs audio", error);
37010
+ end(false);
37011
+ }
37012
+ };
37013
+ const end = (success, error) => {
37014
+ if (ended) return;
37015
+ ended = true;
37016
+ try {
37017
+ if (success) complete();
37018
+ else cancel(error);
37019
+ } catch (loggingError) {
37020
+ debugLogger.error("Error logging ElevenLabs audio", loggingError);
37021
+ cancel();
37022
+ }
37023
+ };
37024
+ if (!isObject(value) || !Object.isExtensible(value)) {
37025
+ end(false);
37026
+ return;
37027
+ }
37028
+ if (typeof value.read === "function" && typeof value.on === "function") {
37029
+ value.on("end", () => end(true));
37030
+ value.on("close", () => end(false));
37031
+ const emit2 = value.emit;
37032
+ if (typeof emit2 === "function")
37033
+ value.emit = function(event, ...args) {
37034
+ if (event === "data" && args[0] instanceof Uint8Array)
37035
+ safeObserve(args[0]);
37036
+ if (event === "error") end(false, args[0]);
37037
+ return Reflect.apply(emit2, this, [event, ...args]);
37038
+ };
37039
+ return;
37040
+ }
37041
+ if (typeof value.getReader === "function") {
37042
+ const webStream = value;
37043
+ const pipeTo = webStream.pipeTo;
37044
+ const pipeThrough = webStream.pipeThrough;
37045
+ webStream.pipeTo = function(destination, options) {
37046
+ if (!isObject(destination) || this.locked || destination.locked)
37047
+ return pipeTo.call(this, destination, options);
37048
+ const tap = new TransformStream({
37049
+ transform(chunk, controller) {
37050
+ safeObserve(chunk);
37051
+ controller.enqueue(chunk);
37052
+ },
37053
+ flush() {
37054
+ end(true);
37055
+ }
37056
+ });
37057
+ const observed = pipeThrough.call(
37058
+ this,
37059
+ tap,
37060
+ options
37061
+ );
37062
+ return observed.pipeTo(destination, options).catch((error) => {
37063
+ end(false, error);
37064
+ throw error;
37065
+ });
37066
+ };
37067
+ webStream.pipeThrough = function(transform, options) {
37068
+ if (this.locked || transform.writable.locked || transform.readable.locked)
37069
+ return pipeThrough.call(this, transform, options);
37070
+ const result = webStream.pipeTo.call(this, transform.writable, options);
37071
+ void result.catch(() => {
37072
+ });
37073
+ return transform.readable;
37074
+ };
37075
+ const getReader = value.getReader;
37076
+ value.getReader = function(...args) {
37077
+ const reader = Reflect.apply(getReader, this, args);
37078
+ const read3 = reader.read;
37079
+ reader.read = function(...readArgs) {
37080
+ return Promise.resolve(
37081
+ withCurrent(span, () => Reflect.apply(read3, this, readArgs))
37082
+ ).then(
37083
+ (result) => {
37084
+ if (result.value) safeObserve(result.value);
37085
+ if (result.done) end(true);
37086
+ return result;
37087
+ },
37088
+ (error) => {
37089
+ end(false, error);
37090
+ throw error;
37091
+ }
37092
+ );
37093
+ };
37094
+ const readerCancel = reader.cancel;
37095
+ reader.cancel = function(...cancelArgs) {
37096
+ const result = Reflect.apply(readerCancel, this, cancelArgs);
37097
+ end(false);
37098
+ return result;
37099
+ };
37100
+ return reader;
37101
+ };
37102
+ const streamCancel = value.cancel;
37103
+ if (typeof streamCancel === "function")
37104
+ value.cancel = function(...args) {
37105
+ const result = Reflect.apply(streamCancel, this, args);
37106
+ void Promise.resolve(result).then(
37107
+ () => end(false),
37108
+ () => {
37109
+ }
37110
+ );
37111
+ return result;
37112
+ };
37113
+ }
37114
+ if (typeof value.getReader === "function" && typeof value.values === "function") {
37115
+ const values = value.values;
37116
+ const iterate = function(...args) {
37117
+ const iterator = Reflect.apply(values, this, args);
37118
+ patchStreamIfNeeded(iterator, {
37119
+ shouldCollect(chunk) {
37120
+ safeObserve(chunk);
37121
+ return false;
37122
+ },
37123
+ onComplete: () => end(true),
37124
+ onCancel: () => end(false),
37125
+ onError: (error) => end(false, error),
37126
+ aroundNext: (next) => withCurrent(span, next)
37127
+ });
37128
+ return iterator;
37129
+ };
37130
+ value.values = iterate;
37131
+ Object.defineProperty(value, Symbol.asyncIterator, {
37132
+ configurable: true,
37133
+ writable: true,
37134
+ value: iterate
37135
+ });
37136
+ } else if (isAsyncIterable(value)) {
37137
+ patchStreamIfNeeded(value, {
37138
+ shouldCollect: (chunk) => {
37139
+ safeObserve(chunk);
37140
+ return false;
37141
+ },
37142
+ onComplete: () => end(true),
37143
+ onCancel: () => end(false),
37144
+ onError: (error) => end(false, error),
37145
+ aroundNext: (next) => withCurrent(span, next)
37146
+ });
37147
+ } else if (typeof value.getReader !== "function") end(false);
37148
+ }
37149
+
36311
37150
  // src/instrumentation/plugins/voyageai-channels.ts
36312
37151
  var voyageAIChannels = defineChannels(
36313
37152
  "voyageai",
@@ -36375,7 +37214,7 @@ var VoyageAIPlugin = class extends BasePlugin {
36375
37214
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
36376
37215
  }
36377
37216
  };
36378
- function interceptVoyageAICall(channel2, name, extractInput3, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
37217
+ function interceptVoyageAICall(channel2, name, extractInput4, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
36379
37218
  return channel2.intercept((target, thisArg, args) => {
36380
37219
  const invokeTarget = () => Reflect.apply(target, thisArg, args);
36381
37220
  if (isAutoInstrumentationSuppressed()) {
@@ -36383,7 +37222,7 @@ function interceptVoyageAICall(channel2, name, extractInput3, extractOutput2, ex
36383
37222
  }
36384
37223
  let span;
36385
37224
  try {
36386
- const { input, metadata } = extractInput3(args);
37225
+ const { input, metadata } = extractInput4(args);
36387
37226
  span = startSpan(
36388
37227
  withSpanInstrumentationName(
36389
37228
  {
@@ -37182,6 +38021,7 @@ var BraintrustPlugin = class extends BasePlugin {
37182
38021
  cloudflareThinkPlugin = null;
37183
38022
  cursorSDKPlugin = null;
37184
38023
  openAIAgentsPlugin = null;
38024
+ googleGenerativeAIPlugin = null;
37185
38025
  googleGenAIPlugin = null;
37186
38026
  huggingFacePlugin = null;
37187
38027
  huggingFaceTransformersPlugin = null;
@@ -37200,6 +38040,7 @@ var BraintrustPlugin = class extends BasePlugin {
37200
38040
  langSmithPlugin = null;
37201
38041
  piCodingAgentPlugin = null;
37202
38042
  strandsAgentSDKPlugin = null;
38043
+ elevenLabsPlugin = null;
37203
38044
  voyageAIPlugin = null;
37204
38045
  cloudflareAIChatPlugin = null;
37205
38046
  cloudflareAgentsPlugin = null;
@@ -37241,6 +38082,10 @@ var BraintrustPlugin = class extends BasePlugin {
37241
38082
  this.openAIAgentsPlugin = new OpenAIAgentsPlugin();
37242
38083
  this.openAIAgentsPlugin.enable();
37243
38084
  }
38085
+ if (integrations.googleGenerativeAI !== false) {
38086
+ this.googleGenerativeAIPlugin = new GoogleGenerativeAIPlugin();
38087
+ this.googleGenerativeAIPlugin.enable();
38088
+ }
37244
38089
  if (integrations.googleGenAI !== false && integrations.google !== false) {
37245
38090
  this.googleGenAIPlugin = new GoogleGenAIPlugin();
37246
38091
  this.googleGenAIPlugin.enable();
@@ -37275,6 +38120,10 @@ var BraintrustPlugin = class extends BasePlugin {
37275
38120
  this.coherePlugin = new CoherePlugin();
37276
38121
  this.coherePlugin.enable();
37277
38122
  }
38123
+ if (integrations.elevenlabs !== false) {
38124
+ this.elevenLabsPlugin = new ElevenLabsPlugin();
38125
+ this.elevenLabsPlugin.enable();
38126
+ }
37278
38127
  if (integrations.voyageai !== false) {
37279
38128
  this.voyageAIPlugin = new VoyageAIPlugin();
37280
38129
  this.voyageAIPlugin.enable();
@@ -37359,6 +38208,10 @@ var BraintrustPlugin = class extends BasePlugin {
37359
38208
  this.openAIAgentsPlugin.disable();
37360
38209
  this.openAIAgentsPlugin = null;
37361
38210
  }
38211
+ if (this.googleGenerativeAIPlugin) {
38212
+ this.googleGenerativeAIPlugin.disable();
38213
+ this.googleGenerativeAIPlugin = null;
38214
+ }
37362
38215
  if (this.googleGenAIPlugin) {
37363
38216
  this.googleGenAIPlugin.disable();
37364
38217
  this.googleGenAIPlugin = null;
@@ -37395,6 +38248,10 @@ var BraintrustPlugin = class extends BasePlugin {
37395
38248
  this.coherePlugin.disable();
37396
38249
  this.coherePlugin = null;
37397
38250
  }
38251
+ if (this.elevenLabsPlugin) {
38252
+ this.elevenLabsPlugin.disable();
38253
+ this.elevenLabsPlugin = null;
38254
+ }
37398
38255
  if (this.voyageAIPlugin) {
37399
38256
  this.voyageAIPlugin.disable();
37400
38257
  this.voyageAIPlugin = null;
@@ -37488,6 +38345,8 @@ var envIntegrationAliases = {
37488
38345
  "openai-agents-core": "openAIAgents",
37489
38346
  openaiagentscore: "openAIAgents",
37490
38347
  google: "google",
38348
+ "google-generative-ai": "googleGenerativeAI",
38349
+ googlegenerativeai: "googleGenerativeAI",
37491
38350
  "google-genai": "googleGenAI",
37492
38351
  googlegenai: "googleGenAI",
37493
38352
  huggingface: "huggingface",
@@ -37521,7 +38380,9 @@ var envIntegrationAliases = {
37521
38380
  langsmith: "langsmith",
37522
38381
  voyage: "voyageai",
37523
38382
  "voyage-ai": "voyageai",
37524
- voyageai: "voyageai"
38383
+ voyageai: "voyageai",
38384
+ elevenlabs: "elevenlabs",
38385
+ "@elevenlabs/elevenlabs-js": "elevenlabs"
37525
38386
  };
37526
38387
  function getDefaultInstrumentationIntegrations() {
37527
38388
  return {
@@ -37532,6 +38393,7 @@ function getDefaultInstrumentationIntegrations() {
37532
38393
  aisdk: true,
37533
38394
  google: true,
37534
38395
  googleGenAI: true,
38396
+ googleGenerativeAI: true,
37535
38397
  googleADK: true,
37536
38398
  huggingface: true,
37537
38399
  claudeAgentSDK: true,
@@ -37557,6 +38419,7 @@ function getDefaultInstrumentationIntegrations() {
37557
38419
  langgraph: true,
37558
38420
  langsmith: true,
37559
38421
  voyageai: true,
38422
+ elevenlabs: true,
37560
38423
  piCodingAgent: true,
37561
38424
  strandsAgentSDK: true,
37562
38425
  cloudflareAgents: true
@@ -37875,9 +38738,11 @@ __export(exports_exports, {
37875
38738
  wrapCohere: () => wrapCohere,
37876
38739
  wrapCopilotClient: () => wrapCopilotClient,
37877
38740
  wrapCursorSDK: () => wrapCursorSDK,
38741
+ wrapElevenLabs: () => wrapElevenLabs,
37878
38742
  wrapGenkit: () => wrapGenkit,
37879
38743
  wrapGoogleADK: () => wrapGoogleADK,
37880
38744
  wrapGoogleGenAI: () => wrapGoogleGenAI,
38745
+ wrapGoogleGenerativeAI: () => wrapGoogleGenerativeAI,
37881
38746
  wrapGroq: () => wrapGroq,
37882
38747
  wrapHuggingFace: () => wrapHuggingFace,
37883
38748
  wrapHuggingFaceTransformers: () => wrapHuggingFaceTransformers,
@@ -39487,7 +40352,7 @@ function extractToolCallsFromBlocks(blocks) {
39487
40352
  if (!Array.isArray(blocks)) return [];
39488
40353
  return extractToolCallsFromSteps([{ content: blocks }]);
39489
40354
  }
39490
- function extractInput2(params) {
40355
+ function extractInput3(params) {
39491
40356
  return params?.prompt ?? params?.messages ?? params?.system;
39492
40357
  }
39493
40358
  var V2_EXCLUDE_KEYS = /* @__PURE__ */ new Set([
@@ -39509,7 +40374,7 @@ function BraintrustMiddleware(config = {}) {
39509
40374
  params,
39510
40375
  model: modelFromWrapGenerate
39511
40376
  }) => {
39512
- const rawInput = extractInput2(params);
40377
+ const rawInput = extractInput3(params);
39513
40378
  const processedInput = processInputAttachments(rawInput);
39514
40379
  const spanArgs = {
39515
40380
  name: config.spanInfo?.name || "ai-sdk.doGenerate",
@@ -39573,7 +40438,7 @@ function BraintrustMiddleware(config = {}) {
39573
40438
  }
39574
40439
  },
39575
40440
  wrapStream: async ({ doStream, params }) => {
39576
- const rawInput = extractInput2(params);
40441
+ const rawInput = extractInput3(params);
39577
40442
  const processedInput = processInputAttachments(rawInput);
39578
40443
  const spanArgs = {
39579
40444
  name: config.spanInfo?.name || "ai-sdk.doStream",
@@ -42966,6 +43831,75 @@ function isModuleNamespace5(value) {
42966
43831
  }
42967
43832
  }
42968
43833
 
43834
+ // src/wrappers/google-generative-ai.ts
43835
+ function wrapGoogleGenerativeAI(client) {
43836
+ if (!isObject(client) || typeof client.getGenerativeModel !== "function")
43837
+ return client;
43838
+ return wrapClient(client);
43839
+ }
43840
+ var proxies = /* @__PURE__ */ new WeakMap();
43841
+ function wrapClient(client) {
43842
+ const cached = proxies.get(client);
43843
+ if (cached) return cached;
43844
+ const proxy = new Proxy(client, {
43845
+ get(target, prop, receiver) {
43846
+ const value = Reflect.get(target, prop, receiver);
43847
+ if (typeof value !== "function") return value;
43848
+ if (prop === "getGenerativeModel" || prop === "getGenerativeModelFromCachedContent" || prop === "startChat") {
43849
+ return (...args) => wrapClient(Reflect.apply(value, target, args));
43850
+ }
43851
+ switch (prop) {
43852
+ case "generateContent":
43853
+ return (...args) => googleGenerativeAIChannels.generateContent.invoke(
43854
+ value,
43855
+ target,
43856
+ args,
43857
+ {}
43858
+ );
43859
+ case "generateContentStream":
43860
+ return (...args) => googleGenerativeAIChannels.generateContentStream.invoke(
43861
+ value,
43862
+ target,
43863
+ args,
43864
+ {}
43865
+ );
43866
+ case "embedContent":
43867
+ return (...args) => googleGenerativeAIChannels.embedContent.invoke(
43868
+ value,
43869
+ target,
43870
+ args,
43871
+ {}
43872
+ );
43873
+ case "batchEmbedContents":
43874
+ return (...args) => googleGenerativeAIChannels.batchEmbedContents.invoke(
43875
+ value,
43876
+ target,
43877
+ args,
43878
+ {}
43879
+ );
43880
+ case "sendMessage":
43881
+ return (...args) => googleGenerativeAIChannels.sendMessage.invoke(
43882
+ value,
43883
+ target,
43884
+ args,
43885
+ {}
43886
+ );
43887
+ case "sendMessageStream":
43888
+ return (...args) => googleGenerativeAIChannels.sendMessageStream.invoke(
43889
+ value,
43890
+ target,
43891
+ args,
43892
+ {}
43893
+ );
43894
+ }
43895
+ return value.bind(target);
43896
+ }
43897
+ });
43898
+ proxies.set(client, proxy);
43899
+ proxies.set(proxy, proxy);
43900
+ return proxy;
43901
+ }
43902
+
42969
43903
  // src/wrappers/google-genai.ts
42970
43904
  function wrapGoogleGenAI(googleGenAI) {
42971
43905
  if (!googleGenAI || typeof googleGenAI !== "object") {
@@ -44963,8 +45897,8 @@ function normalizeScores(result) {
44963
45897
  (s) => s !== null && s !== void 0 && typeof s === "object" && isScore(s)
44964
45898
  );
44965
45899
  }
44966
- if (typeof result === "object" && result !== null && isScore(result)) {
44967
- return [result];
45900
+ if (typeof result === "object" && result !== null && "score" in result) {
45901
+ return [{ ...result, name: result.name ?? "score" }];
44968
45902
  }
44969
45903
  return [];
44970
45904
  }
@@ -47547,19 +48481,29 @@ function buildSpanScores(results) {
47547
48481
  function _internalPrepareEvaluatorScore(scoreValue, name) {
47548
48482
  if (scoreValue === null) return { results: null };
47549
48483
  if (Array.isArray(scoreValue)) {
48484
+ const names = /* @__PURE__ */ new Set();
47550
48485
  for (const score of scoreValue) {
47551
48486
  if (!(typeof score === "object" && !isEmpty2(score))) {
47552
48487
  throw new Error(
47553
48488
  `When returning an array of scores, each score must be a non-empty object. Got: ${JSON.stringify(score)}`
47554
48489
  );
47555
48490
  }
48491
+ if (typeof score.name !== "string") {
48492
+ throw new Error(
48493
+ `When returning an array of scores, each score must have a name. Got: ${JSON.stringify(score)}`
48494
+ );
48495
+ }
48496
+ if (names.has(score.name)) {
48497
+ throw new Error(`Duplicate score name '${score.name}' in score array`);
48498
+ }
48499
+ names.add(score.name);
47556
48500
  }
47557
48501
  }
47558
48502
  let results;
47559
48503
  if (Array.isArray(scoreValue)) {
47560
48504
  results = scoreValue;
47561
48505
  } else if (typeof scoreValue === "object" && !isEmpty2(scoreValue)) {
47562
- results = [scoreValue];
48506
+ results = [{ ...scoreValue, name: scoreValue.name ?? name }];
47563
48507
  } else {
47564
48508
  results = [{ name, score: scoreValue }];
47565
48509
  }
@@ -50317,6 +51261,65 @@ var evaluatorDefinitionsSchema = z13.record(
50317
51261
  evaluatorDefinitionSchema
50318
51262
  );
50319
51263
 
51264
+ // src/wrappers/elevenlabs.ts
51265
+ var clients = /* @__PURE__ */ new WeakMap();
51266
+ function wrapElevenLabs(client) {
51267
+ if (!isObject(client) || !isObject(client.textToSpeech) || typeof client.textToSpeech.convert !== "function") {
51268
+ debugLogger.warn("Unsupported ElevenLabs client. Not wrapping.");
51269
+ return client;
51270
+ }
51271
+ const cached = clients.get(client);
51272
+ if (cached) return cached;
51273
+ const sdk = client;
51274
+ const speech = new Proxy(sdk.textToSpeech, {
51275
+ get(target, prop, receiver) {
51276
+ switch (prop) {
51277
+ case "convert":
51278
+ case "stream":
51279
+ return (...args) => elevenLabsChannels[prop].invoke(target[prop], target, args, {});
51280
+ case "convertWithTimestamps":
51281
+ return (...args) => elevenLabsChannels.convertWithTimestamps.invoke(
51282
+ target.convertWithTimestamps,
51283
+ target,
51284
+ args,
51285
+ {}
51286
+ );
51287
+ case "streamWithTimestamps":
51288
+ return (...args) => elevenLabsChannels.streamWithTimestamps.invoke(
51289
+ target.streamWithTimestamps,
51290
+ target,
51291
+ args,
51292
+ {}
51293
+ );
51294
+ default:
51295
+ return Reflect.get(target, prop, receiver);
51296
+ }
51297
+ }
51298
+ });
51299
+ const transcription = new Proxy(sdk.speechToText, {
51300
+ get(target, prop, receiver) {
51301
+ if (prop === "convert")
51302
+ return (request, options) => elevenLabsChannels.transcribe.invoke(
51303
+ target.convert,
51304
+ target,
51305
+ [request, options],
51306
+ {}
51307
+ );
51308
+ return Reflect.get(target, prop, receiver);
51309
+ }
51310
+ });
51311
+ const proxy = new Proxy(sdk, {
51312
+ get(target, prop, receiver) {
51313
+ if (prop === "textToSpeech") return speech;
51314
+ if (prop === "speechToText") return transcription;
51315
+ return Reflect.get(target, prop, receiver);
51316
+ }
51317
+ });
51318
+ clients.set(client, proxy);
51319
+ clients.set(proxy, proxy);
51320
+ return proxy;
51321
+ }
51322
+
50320
51323
  // src/browser/index.ts
50321
51324
  configureBrowser();
50322
51325
  export {
@@ -50482,9 +51485,11 @@ export {
50482
51485
  wrapCohere,
50483
51486
  wrapCopilotClient,
50484
51487
  wrapCursorSDK,
51488
+ wrapElevenLabs,
50485
51489
  wrapGenkit,
50486
51490
  wrapGoogleADK,
50487
51491
  wrapGoogleGenAI,
51492
+ wrapGoogleGenerativeAI,
50488
51493
  wrapGroq,
50489
51494
  wrapHuggingFace,
50490
51495
  wrapHuggingFaceTransformers,