@ai-sdk/otel 1.0.123 → 1.0.126

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # @ai-sdk/otel
2
2
 
3
+ ## 1.0.126
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [4f3d236]
8
+ - ai@7.0.126
9
+
10
+ ## 1.0.125
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies [ff3dcef]
15
+ - ai@7.0.125
16
+
17
+ ## 1.0.124
18
+
19
+ ### Patch Changes
20
+
21
+ - 8c65988: feat(ai): add telemetry to speech generation and transcription, including
22
+ provider usage propagation and experimental streaming lifecycle callbacks
23
+ - Updated dependencies [8c65988]
24
+ - ai@7.0.124
25
+ - @ai-sdk/provider@4.0.21
26
+
3
27
  ## 1.0.123
4
28
 
5
29
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Attributes, Tracer } from "@opentelemetry/api";
2
- import { EmbedEndEvent, EmbedStartEvent, EmbeddingModelCallEndEvent, EmbeddingModelCallStartEvent, Experimental_EvaluateEndEvent, Experimental_EvaluateStartEvent, Experimental_EvaluationModelCallEndEvent, Experimental_EvaluationModelCallStartEvent, GenerateObjectEndEvent, GenerateObjectStartEvent, GenerateObjectStepEndEvent, GenerateObjectStepStartEvent, GenerateTextAbortEvent, GenerateTextEndEvent, GenerateTextStartEvent, GenerateTextStepEndEvent, GenerateTextStepStartEvent, InferTelemetryEvent, LanguageModelCallEndEvent, LanguageModelCallStartEvent, Output, RerankEndEvent, RerankStartEvent, RerankingModelCallEndEvent, RerankingModelCallStartEvent, Telemetry, ToolExecutionEndEvent, ToolExecutionStartEvent, ToolSet } from "ai";
2
+ import { EmbedEndEvent, EmbedStartEvent, EmbeddingModelCallEndEvent, EmbeddingModelCallStartEvent, Experimental_EvaluateEndEvent, Experimental_EvaluateStartEvent, Experimental_EvaluationModelCallEndEvent, Experimental_EvaluationModelCallStartEvent, Experimental_StreamTranscriptionEndEvent, Experimental_StreamTranscriptionStartEvent, GenerateObjectEndEvent, GenerateObjectStartEvent, GenerateObjectStepEndEvent, GenerateObjectStepStartEvent, GenerateSpeechEndEvent, GenerateSpeechStartEvent, GenerateTextAbortEvent, GenerateTextEndEvent, GenerateTextStartEvent, GenerateTextStepEndEvent, GenerateTextStepStartEvent, InferTelemetryEvent, LanguageModelCallEndEvent, LanguageModelCallStartEvent, Output, RerankEndEvent, RerankStartEvent, RerankingModelCallEndEvent, RerankingModelCallStartEvent, Telemetry, ToolExecutionEndEvent, ToolExecutionStartEvent, ToolSet, TranscriptionEndEvent, TranscriptionStartEvent } from "ai";
3
3
  import { APICallError, LanguageModelV4Prompt } from "@ai-sdk/provider";
4
4
  //#region src/supplemental-attributes.d.ts
5
5
  type OpenTelemetrySpanType = 'operation' | 'step' | 'languageModel' | 'tool' | 'embedding' | 'reranking' | 'experimental_evaluation';
@@ -83,7 +83,9 @@ export declare class OpenTelemetry implements Telemetry {
83
83
  callId: string;
84
84
  execute: () => PromiseLike<T>;
85
85
  }): PromiseLike<T>;
86
- onStart(event: InferTelemetryEvent<GenerateTextStartEvent> | InferTelemetryEvent<GenerateObjectStartEvent> | InferTelemetryEvent<EmbedStartEvent> | InferTelemetryEvent<RerankStartEvent>): void;
86
+ onStart(event: InferTelemetryEvent<GenerateTextStartEvent> | InferTelemetryEvent<GenerateObjectStartEvent> | InferTelemetryEvent<EmbedStartEvent> | InferTelemetryEvent<RerankStartEvent> | InferTelemetryEvent<GenerateSpeechStartEvent> | InferTelemetryEvent<TranscriptionStartEvent>): void;
87
+ experimental_onStreamTranscriptionStart(event: InferTelemetryEvent<Experimental_StreamTranscriptionStartEvent>): void;
88
+ private onAudioOperationStart;
87
89
  private onGenerateStart;
88
90
  private onObjectOperationStart;
89
91
  /** @deprecated */
@@ -99,7 +101,9 @@ export declare class OpenTelemetry implements Telemetry {
99
101
  onStepEnd(event: GenerateTextStepEndEvent<ToolSet>): void;
100
102
  /** @deprecated Use `onStepEnd` instead. */
101
103
  onStepFinish(event: GenerateTextStepEndEvent<ToolSet>): void;
102
- onEnd(event: GenerateTextEndEvent<ToolSet> | GenerateObjectEndEvent<unknown> | EmbedEndEvent | RerankEndEvent): void;
104
+ onEnd(event: GenerateTextEndEvent<ToolSet> | GenerateObjectEndEvent<unknown> | EmbedEndEvent | RerankEndEvent | GenerateSpeechEndEvent | TranscriptionEndEvent): void;
105
+ experimental_onStreamTranscriptionEnd(event: InferTelemetryEvent<Experimental_StreamTranscriptionEndEvent>): void;
106
+ private onAudioOperationEnd;
103
107
  private onGenerateEnd;
104
108
  private onObjectOperationEnd;
105
109
  private onEmbedOperationEnd;
@@ -162,7 +166,9 @@ export declare class LegacyOpenTelemetry implements Telemetry {
162
166
  callId: string;
163
167
  execute: () => PromiseLike<T>;
164
168
  }): PromiseLike<T>;
165
- onStart(event: InferTelemetryEvent<GenerateTextStartEvent> | InferTelemetryEvent<GenerateObjectStartEvent> | InferTelemetryEvent<EmbedStartEvent> | InferTelemetryEvent<RerankStartEvent>): void;
169
+ onStart(event: InferTelemetryEvent<GenerateTextStartEvent> | InferTelemetryEvent<GenerateObjectStartEvent> | InferTelemetryEvent<EmbedStartEvent> | InferTelemetryEvent<RerankStartEvent> | InferTelemetryEvent<GenerateSpeechStartEvent> | InferTelemetryEvent<TranscriptionStartEvent>): void;
170
+ experimental_onStreamTranscriptionStart(event: InferTelemetryEvent<Experimental_StreamTranscriptionStartEvent>): void;
171
+ private onAudioOperationStart;
166
172
  private onGenerateStart;
167
173
  private onObjectOperationStart;
168
174
  /** @deprecated */
@@ -176,7 +182,9 @@ export declare class LegacyOpenTelemetry implements Telemetry {
176
182
  onStepEnd(event: GenerateTextStepEndEvent<ToolSet>): void;
177
183
  /** @deprecated Use `onStepEnd` instead. */
178
184
  onStepFinish(event: GenerateTextStepEndEvent<ToolSet>): void;
179
- onEnd(event: GenerateTextEndEvent<ToolSet> | GenerateObjectEndEvent<unknown> | EmbedEndEvent | RerankEndEvent): void;
185
+ onEnd(event: GenerateTextEndEvent<ToolSet> | GenerateObjectEndEvent<unknown> | EmbedEndEvent | RerankEndEvent | GenerateSpeechEndEvent | TranscriptionEndEvent): void;
186
+ experimental_onStreamTranscriptionEnd(event: InferTelemetryEvent<Experimental_StreamTranscriptionEndEvent>): void;
187
+ private onAudioOperationEnd;
180
188
  private onGenerateEnd;
181
189
  private onObjectOperationEnd;
182
190
  private onEmbedOperationEnd;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":["OtelStepStartEvent","EvaluateStartEvent","EvaluateEndEvent","EvaluationModelCallStartEvent","EvaluationModelCallEndEvent","AISDKContext","EvaluateStartEvent","EvaluateEndEvent","EvaluationModelCallStartEvent","EvaluationModelCallEndEvent"],"sources":["../src/supplemental-attributes.ts","../src/open-telemetry.ts","../../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/schemas.d.cts","../../provider-utils/dist/index.d.ts","../src/legacy-open-telemetry.ts"],"x_google_ignoreList":[2],"mappings":";;;;KAwBY;KASA,cAAc;EACxB,UAAU;EACV;EACA;EACA,gBAAgB;MACZ;KAEM;;;;EAIV,SAAS;;;;;EAMT,aAAa;;;;EAKb;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA;;;;UCzBQA,6BAA2B,2BAA2B;WACrD;;qBA2CE,yBAAyB;mBACnB;mBAEA;mBACA;mBACA;EAEL,YAAA,UAAS;UAMb;UAIA;UAIA;EAgCR,YAAY,KACV,QACA,YACA;IAEA;IACA;IACA,eAAe,YAAY;MACzB,YAAY;;;;;EAchB,yBAAyB,KACvB,QACA;IAEA;IACA,eAAe,YAAY;MACzB,YAAY;EAWhB,QACE,OACI,oBAAoB,0BACpB,oBAAoB,4BACpB,oBAAoB,mBACpB,oBAAoB;UA8BlB;UAuGA;;EA6GR,kBAAkB,OAAO;;EAuEzB,gBAAgB,OAAO;UAiDf;EA6ER,YAAY,OAAOA;EAwCnB,yBAAyB,OAAO;EAyEhC,uBAAuB,OAAO,0BAA0B;EAiKxD,qBAAqB,OAAO,wBAAwB;EAyCpD,mBAAmB,OAAO,sBAAsB;EAqChD,UAAU,OAAO,yBAAyB;;EAuB1C,aAAa,OAAO,yBAAyB;EAI7C,MACE,OACI,qBAAqB,WACrB,kCACA,gBACA;UA6BE;UAiDA;UA2CA;EAoCR,aAAa,OAAO;EA4CpB,WAAW,OAAO;UAgCV;UAoEA;EAQR,cAAc,OAAO;EAyCrB,YAAY,OAAO;UAsBX;UAkEA;EAqBR,6BACE,OAAO,oBAAoBC;EAK7B,2BAA2B,OAAOC;EAIlC,wCACE,OAAOC;EA8CT,sCACE,OAAOC;EA+BT,QAAQ,OAAO,uBAAuB;EAwCtC,QAAQ;;;;QC31BF;YACM;;;;;;;;;KCg2BT,UAAU;;;UCj+CL,mBACR,cAAc,UAAU,SACxB,wBAAwBC,UAAeA,SACvC,eAAe,OAAO,SAAS,OAAO,gBAC9B,2BAA2B,OAAO,iBAAiB;WAClD,iBAAiB;WACjB,YAAY,cAAc;WAC1B;;qBAkBE,+BAA+B;mBACzB;;;;mBAKA;EAGf,YAAA;IACE,SAAS;;UAML;UAIA;EAIR,YAAY,KACV,QACA,YACA;IAEA;IACA;IACA,eAAe,YAAY;MACzB,YAAY;;;;;EAchB,yBAAyB,KACvB,QACA;IAEA;IACA,eAAe,YAAY;MACzB,YAAY;EAUhB,QACE,OACI,oBAAoB,0BACpB,oBAAoB,4BACpB,oBAAoB,mBACpB,oBAAoB;UA8BlB;UAgEA;;EAqER,kBAAkB,OAAO;;EAmDzB,gBAAgB,OAAO;UAuDf;EA6DR,YAAY,OAAO;EAiEnB,qBAAqB,OAAO,wBAAwB;EAqCpD,mBAAmB,OAAO,sBAAsB;EA+BhD,UAAU,OAAO,yBAAyB;;EA4G1C,aAAa,OAAO,yBAAyB;EAI7C,MACE,OACI,qBAAqB,WACrB,kCACA,gBACA;UA6BE;UAyEA;UA+BA;EA6BR,aAAa,OAAO;EA8BpB,WAAW,OAAO;UAwBV;UAkDA;EAQR,cAAc,OAAO;EA2BrB,YAAY,OAAO;UAoBX;UA8CA;EAeR,6BACE,OAAO,oBAAoBC;EAK7B,2BAA2B,OAAOC;EAIlC,wCACE,OAAOC;EA6BT,sCACE,OAAOC;EAqBT,QAAQ,OAAO,uBAAuB;EAkCtC,QAAQ"}
1
+ {"version":3,"file":"index.d.ts","names":["OtelStepStartEvent","StreamTranscriptionStartEvent","StreamTranscriptionEndEvent","EvaluateStartEvent","EvaluateEndEvent","EvaluationModelCallStartEvent","EvaluationModelCallEndEvent","AISDKContext","StreamTranscriptionStartEvent","StreamTranscriptionEndEvent","EvaluateStartEvent","EvaluateEndEvent","EvaluationModelCallStartEvent","EvaluationModelCallEndEvent"],"sources":["../src/supplemental-attributes.ts","../src/open-telemetry.ts","../../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/schemas.d.cts","../../provider-utils/dist/index.d.ts","../src/legacy-open-telemetry.ts"],"x_google_ignoreList":[2],"mappings":";;;;KAwBY;KASA,cAAc;EACxB,UAAU;EACV;EACA;EACA,gBAAgB;MACZ;KAEM;;;;EAIV,SAAS;;;;;EAMT,aAAa;;;;EAKb;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA;;;;UClBQA,6BAA2B,2BAA2B;WACrD;;qBA2CE,yBAAyB;mBACnB;mBAEA;mBACA;mBACA;EAEL,YAAA,UAAS;UAMb;UAIA;UAIA;EAgCR,YAAY,KACV,QACA,YACA;IAEA;IACA;IACA,eAAe,YAAY;MACzB,YAAY;;;;;EAchB,yBAAyB,KACvB,QACA;IAEA;IACA,eAAe,YAAY;MACzB,YAAY;EAWhB,QACE,OACI,oBAAoB,0BACpB,oBAAoB,4BACpB,oBAAoB,mBACpB,oBAAoB,oBACpB,oBAAoB,4BACpB,oBAAoB;EA4C1B,wCACE,OAAO,oBAAoBC;UAKrB;UA0FA;UAuGA;;EA6GR,kBAAkB,OAAO;;EAuEzB,gBAAgB,OAAO;UAiDf;EA6ER,YAAY,OAAOD;EAwCnB,yBAAyB,OAAO;EAyEhC,uBAAuB,OAAO,0BAA0B;EAiKxD,qBAAqB,OAAO,wBAAwB;EAyCpD,mBAAmB,OAAO,sBAAsB;EAqChD,UAAU,OAAO,yBAAyB;;EAuB1C,aAAa,OAAO,yBAAyB;EAI7C,MACE,OACI,qBAAqB,WACrB,kCACA,gBACA,iBACA,yBACA;EAuCN,sCACE,OAAO,oBAAoBE;UAKrB;UA8EA;UAiDA;UA2CA;EAoCR,aAAa,OAAO;EA4CpB,WAAW,OAAO;UAgCV;UAoEA;EAQR,cAAc,OAAO;EAyCrB,YAAY,OAAO;UAsBX;UAkEA;EAqBR,6BACE,OAAO,oBAAoBC;EAK7B,2BAA2B,OAAOC;EAIlC,wCACE,OAAOC;EA8CT,sCACE,OAAOC;EA+BT,QAAQ,OAAO,uBAAuB;EAwCtC,QAAQ;;;;QCljCF;YACM;;;;;;;;;KC22BT,UAAU;;;UCr+CL,mBACR,cAAc,UAAU,SACxB,wBAAwBC,UAAeA,SACvC,eAAe,OAAO,SAAS,OAAO,gBAC9B,2BAA2B,OAAO,iBAAiB;WAClD,iBAAiB;WACjB,YAAY,cAAc;WAC1B;;qBAkBE,+BAA+B;mBACzB;;;;mBAKA;EAGf,YAAA;IACE,SAAS;;UAML;UAIA;EAIR,YAAY,KACV,QACA,YACA;IAEA;IACA;IACA,eAAe,YAAY;MACzB,YAAY;;;;;EAchB,yBAAyB,KACvB,QACA;IAEA;IACA,eAAe,YAAY;MACzB,YAAY;EAUhB,QACE,OACI,oBAAoB,0BACpB,oBAAoB,4BACpB,oBAAoB,mBACpB,oBAAoB,oBACpB,oBAAoB,4BACpB,oBAAoB;EA4C1B,wCACE,OAAO,oBAAoBC;UAKrB;UAyDA;UAgEA;;EAqER,kBAAkB,OAAO;;EAmDzB,gBAAgB,OAAO;UAuDf;EA6DR,YAAY,OAAO;EAiEnB,qBAAqB,OAAO,wBAAwB;EAqCpD,mBAAmB,OAAO,sBAAsB;EA+BhD,UAAU,OAAO,yBAAyB;;EA4G1C,aAAa,OAAO,yBAAyB;EAI7C,MACE,OACI,qBAAqB,WACrB,kCACA,gBACA,iBACA,yBACA;EAuCN,sCACE,OAAO,oBAAoBC;UAKrB;UA+CA;UAyEA;UA+BA;EA6BR,aAAa,OAAO;EA8BpB,WAAW,OAAO;UAwBV;UAkDA;EAQR,cAAc,OAAO;EA2BrB,YAAY,OAAO;UAoBX;UA8CA;EAeR,6BACE,OAAO,oBAAoBC;EAK7B,2BAA2B,OAAOC;EAIlC,wCACE,OAAOC;EA6BT,sCACE,OAAOC;EAqBT,QAAQ,OAAO,uBAAuB;EAkCtC,QAAQ"}
package/dist/index.js CHANGED
@@ -46,7 +46,10 @@ function mapOperationName(operationId) {
46
46
  "ai.streamObject": "invoke_agent",
47
47
  "ai.embed": "embeddings",
48
48
  "ai.embedMany": "embeddings",
49
- "ai.rerank": "rerank"
49
+ "ai.rerank": "rerank",
50
+ "ai.generateSpeech": "ai.generateSpeech",
51
+ "ai.transcribe": "ai.transcribe",
52
+ "ai.streamTranscribe": "ai.streamTranscribe"
50
53
  }[operationId] ?? operationId;
51
54
  }
52
55
  /**
@@ -460,6 +463,48 @@ function recordErrorOnSpan(span, error) {
460
463
  } else span.setStatus({ code: SpanStatusCode.ERROR });
461
464
  }
462
465
  //#endregion
466
+ //#region src/provider-usage-attributes.ts
467
+ const usageKeyAliases = {
468
+ inputtokens: "input_tokens",
469
+ prompttokens: "input_tokens",
470
+ prompttokencount: "input_tokens",
471
+ totalinputtokens: "input_tokens",
472
+ outputtokens: "output_tokens",
473
+ completiontokens: "output_tokens",
474
+ completiontokencount: "output_tokens",
475
+ candidatestokencount: "output_tokens",
476
+ totaltokens: "total_tokens",
477
+ totaltokencount: "total_tokens"
478
+ };
479
+ function normalizeUsageKey(key) {
480
+ const aliasKey = key.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
481
+ const alias = usageKeyAliases[aliasKey];
482
+ if (alias != null) return alias;
483
+ return key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toLowerCase();
484
+ }
485
+ /**
486
+ * Converts provider-native usage objects into numeric span attributes.
487
+ *
488
+ * Usage units such as tokens, characters, and seconds remain distinct so
489
+ * observability backends can apply the provider/model-specific price unit.
490
+ */
491
+ function getProviderUsageAttributes({ usage, prefix }) {
492
+ const attributes = {};
493
+ const addValue = (value, path) => {
494
+ if (typeof value === "number") {
495
+ if (Number.isFinite(value) && path.length > 0) attributes[`${prefix}.${path.join(".")}`] = value;
496
+ return;
497
+ }
498
+ if (value == null || typeof value !== "object" || Array.isArray(value)) return;
499
+ for (const [key, nestedValue] of Object.entries(value)) {
500
+ const normalizedKey = normalizeUsageKey(key);
501
+ if (normalizedKey !== "") addValue(nestedValue, [...path, normalizedKey]);
502
+ }
503
+ };
504
+ addValue(usage, []);
505
+ return attributes;
506
+ }
507
+ //#endregion
463
508
  //#region src/sanitize-attribute-value.ts
464
509
  function isPrimitiveAttributeValue(value) {
465
510
  return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
@@ -641,6 +686,14 @@ var OpenTelemetry = class {
641
686
  return context.with(modelCallContext, execute);
642
687
  }
643
688
  onStart(event) {
689
+ if (event.operationId === "ai.generateSpeech") {
690
+ this.onAudioOperationStart(event);
691
+ return;
692
+ }
693
+ if (event.operationId === "ai.transcribe") {
694
+ this.onAudioOperationStart(event);
695
+ return;
696
+ }
644
697
  if (event.operationId === "ai.embed" || event.operationId === "ai.embedMany") {
645
698
  this.onEmbedOperationStart(event);
646
699
  return;
@@ -655,6 +708,70 @@ var OpenTelemetry = class {
655
708
  }
656
709
  this.onGenerateStart(event);
657
710
  }
711
+ experimental_onStreamTranscriptionStart(event) {
712
+ this.onAudioOperationStart(event);
713
+ }
714
+ onAudioOperationStart(event) {
715
+ const telemetry = {
716
+ recordInputs: event.recordInputs,
717
+ recordOutputs: event.recordOutputs,
718
+ functionId: event.functionId
719
+ };
720
+ const providerName = mapProviderName(event.provider);
721
+ const operationName = mapOperationName(event.operationId);
722
+ const audio = "audio" in event ? event.audio : void 0;
723
+ const text = "text" in event ? event.text : void 0;
724
+ const baseSupplementalAttributes = selectSupplementalAttributes(telemetry, this.supplementalAttributes, { headers: getHeaderAttributes(event.headers) });
725
+ const attributes = selectAttributes$1(telemetry, {
726
+ "gen_ai.operation.name": operationName,
727
+ "gen_ai.provider.name": providerName,
728
+ "gen_ai.request.model": event.modelId,
729
+ "gen_ai.agent.name": telemetry.functionId,
730
+ "gen_ai.output.type": event.operationId === "ai.generateSpeech" ? "speech" : "text",
731
+ "gen_ai.request.stream": event.operationId === "ai.streamTranscribe",
732
+ "gen_ai.input.messages": text == null ? void 0 : { input: () => JSON.stringify([{
733
+ role: "user",
734
+ parts: [{
735
+ type: "text",
736
+ content: text
737
+ }]
738
+ }]) },
739
+ "ai.request.text": text == null ? void 0 : { input: () => text },
740
+ "ai.request.audio.size": audio?.byteLength == null ? void 0 : { input: () => audio.byteLength },
741
+ "ai.request.audio.media_type": audio == null ? void 0 : { input: () => audio.mediaType },
742
+ ...baseSupplementalAttributes
743
+ });
744
+ const rootSpan = this.tracer.startSpan(`${operationName} ${event.modelId}`, {
745
+ attributes: this.getSpanAttributes({
746
+ attributes,
747
+ spanType: "operation",
748
+ operationId: event.operationId,
749
+ callId: event.callId,
750
+ runtimeContext: void 0
751
+ }),
752
+ kind: SpanKind.CLIENT
753
+ });
754
+ const rootContext = trace.setSpan(context.active(), rootSpan);
755
+ this.callStates.set(event.callId, {
756
+ operationId: event.operationId,
757
+ telemetry,
758
+ rootSpan,
759
+ rootContext,
760
+ stepSpan: void 0,
761
+ stepContext: void 0,
762
+ inferenceSpan: void 0,
763
+ inferenceContext: void 0,
764
+ embedSpans: /* @__PURE__ */ new Map(),
765
+ rerankSpan: void 0,
766
+ evaluationSpan: void 0,
767
+ toolSpans: /* @__PURE__ */ new Map(),
768
+ settings: {},
769
+ provider: event.provider,
770
+ modelId: event.modelId,
771
+ runtimeContext: void 0,
772
+ baseSupplementalAttributes
773
+ });
774
+ }
658
775
  onGenerateStart(event) {
659
776
  const telemetry = {
660
777
  recordInputs: event.recordInputs,
@@ -1139,12 +1256,51 @@ var OpenTelemetry = class {
1139
1256
  this.onRerankOperationEnd(event);
1140
1257
  return;
1141
1258
  }
1259
+ if (state.operationId === "ai.generateSpeech" || state.operationId === "ai.transcribe") {
1260
+ this.onAudioOperationEnd(event);
1261
+ return;
1262
+ }
1142
1263
  if (state.operationId === "ai.generateObject" || state.operationId === "ai.streamObject") {
1143
1264
  this.onObjectOperationEnd(event);
1144
1265
  return;
1145
1266
  }
1146
1267
  this.onGenerateEnd(event);
1147
1268
  }
1269
+ experimental_onStreamTranscriptionEnd(event) {
1270
+ this.onAudioOperationEnd(event);
1271
+ }
1272
+ onAudioOperationEnd(event) {
1273
+ const state = this.getCallState(event.callId);
1274
+ if (!state?.rootSpan) return;
1275
+ const outputAudio = event.operationId === "ai.generateSpeech" ? event.audio : void 0;
1276
+ const inputAudio = event.operationId === "ai.generateSpeech" ? void 0 : event.audio;
1277
+ const transcript = "segments" in event ? event.text : void 0;
1278
+ state.rootSpan.setAttributes(selectAttributes$1(state.telemetry, {
1279
+ "ai.request.audio.size": inputAudio == null ? void 0 : { input: () => inputAudio.byteLength },
1280
+ "ai.request.audio.media_type": inputAudio == null ? void 0 : { input: () => inputAudio.mediaType },
1281
+ "ai.response.text": transcript == null ? void 0 : { output: () => transcript },
1282
+ "gen_ai.output.messages": transcript == null ? void 0 : { output: () => JSON.stringify([{
1283
+ role: "assistant",
1284
+ parts: [{
1285
+ type: "text",
1286
+ content: transcript
1287
+ }]
1288
+ }]) },
1289
+ "ai.response.audio.size": outputAudio == null ? void 0 : { output: () => outputAudio.byteLength },
1290
+ "ai.response.audio.media_type": outputAudio == null ? void 0 : { output: () => outputAudio.mediaType },
1291
+ "ai.response.audio.format": outputAudio == null || !("format" in outputAudio) ? void 0 : { output: () => String(outputAudio.format) },
1292
+ ...getProviderUsageAttributes({
1293
+ usage: event.usage,
1294
+ prefix: "gen_ai.usage"
1295
+ }),
1296
+ ...selectSupplementalAttributes(state.telemetry, this.supplementalAttributes, {
1297
+ usage: { "ai.response.usage": event.usage == null ? void 0 : JSON.stringify(event.usage) },
1298
+ providerMetadata: { "ai.response.providerMetadata": event.providerMetadata == null ? void 0 : JSON.stringify(event.providerMetadata) }
1299
+ })
1300
+ }));
1301
+ state.rootSpan.end();
1302
+ this.cleanupCallState(event.callId);
1303
+ }
1148
1304
  onGenerateEnd(event) {
1149
1305
  const state = this.getCallState(event.callId);
1150
1306
  if (!state?.rootSpan) return;
@@ -1641,6 +1797,14 @@ var LegacyOpenTelemetry = class {
1641
1797
  return context.with(stepContext, execute);
1642
1798
  }
1643
1799
  onStart(event) {
1800
+ if (event.operationId === "ai.generateSpeech") {
1801
+ this.onAudioOperationStart(event);
1802
+ return;
1803
+ }
1804
+ if (event.operationId === "ai.transcribe") {
1805
+ this.onAudioOperationStart(event);
1806
+ return;
1807
+ }
1644
1808
  if (event.operationId === "ai.embed" || event.operationId === "ai.embedMany") {
1645
1809
  this.onEmbedOperationStart(event);
1646
1810
  return;
@@ -1655,6 +1819,49 @@ var LegacyOpenTelemetry = class {
1655
1819
  }
1656
1820
  this.onGenerateStart(event);
1657
1821
  }
1822
+ experimental_onStreamTranscriptionStart(event) {
1823
+ this.onAudioOperationStart(event);
1824
+ }
1825
+ onAudioOperationStart(event) {
1826
+ const telemetry = {
1827
+ recordInputs: event.recordInputs,
1828
+ recordOutputs: event.recordOutputs,
1829
+ functionId: event.functionId
1830
+ };
1831
+ const audio = "audio" in event ? event.audio : void 0;
1832
+ const text = "text" in event ? event.text : void 0;
1833
+ const baseTelemetryAttributes = {
1834
+ "ai.model.provider": event.provider,
1835
+ "ai.model.id": event.modelId,
1836
+ ...Object.fromEntries(Object.entries(event.headers ?? {}).map(([key, value]) => [`ai.request.headers.${key}`, value]))
1837
+ };
1838
+ const attributes = selectAttributes(telemetry, {
1839
+ ...assembleOperationName({
1840
+ operationId: event.operationId,
1841
+ telemetry
1842
+ }),
1843
+ ...baseTelemetryAttributes,
1844
+ "ai.request.text": text == null ? void 0 : { input: () => text },
1845
+ "ai.request.audio.size": audio?.byteLength == null ? void 0 : { input: () => audio.byteLength },
1846
+ "ai.request.audio.mediaType": audio == null ? void 0 : { input: () => audio.mediaType }
1847
+ });
1848
+ const rootSpan = this.tracer.startSpan(event.operationId, { attributes });
1849
+ const rootContext = trace.setSpan(context.active(), rootSpan);
1850
+ this.callStates.set(event.callId, {
1851
+ operationId: event.operationId,
1852
+ telemetry,
1853
+ rootSpan,
1854
+ rootContext,
1855
+ stepSpan: void 0,
1856
+ stepContext: void 0,
1857
+ embedSpans: /* @__PURE__ */ new Map(),
1858
+ rerankSpan: void 0,
1859
+ evaluationSpan: void 0,
1860
+ toolSpans: /* @__PURE__ */ new Map(),
1861
+ baseTelemetryAttributes,
1862
+ settings: {}
1863
+ });
1864
+ }
1658
1865
  onGenerateStart(event) {
1659
1866
  const telemetry = {
1660
1867
  recordInputs: event.recordInputs,
@@ -2006,12 +2213,41 @@ var LegacyOpenTelemetry = class {
2006
2213
  this.onRerankOperationEnd(event);
2007
2214
  return;
2008
2215
  }
2216
+ if (state.operationId === "ai.generateSpeech" || state.operationId === "ai.transcribe") {
2217
+ this.onAudioOperationEnd(event);
2218
+ return;
2219
+ }
2009
2220
  if (state.operationId === "ai.generateObject" || state.operationId === "ai.streamObject") {
2010
2221
  this.onObjectOperationEnd(event);
2011
2222
  return;
2012
2223
  }
2013
2224
  this.onGenerateEnd(event);
2014
2225
  }
2226
+ experimental_onStreamTranscriptionEnd(event) {
2227
+ this.onAudioOperationEnd(event);
2228
+ }
2229
+ onAudioOperationEnd(event) {
2230
+ const state = this.getCallState(event.callId);
2231
+ if (!state?.rootSpan) return;
2232
+ const isSpeech = event.operationId === "ai.generateSpeech";
2233
+ const audio = event.audio;
2234
+ state.rootSpan.setAttributes(selectAttributes(state.telemetry, {
2235
+ "ai.request.audio.size": isSpeech ? void 0 : { input: () => audio.byteLength },
2236
+ "ai.request.audio.mediaType": isSpeech ? void 0 : { input: () => audio.mediaType },
2237
+ "ai.response.text": "segments" in event ? { output: () => event.text } : void 0,
2238
+ "ai.response.audio.size": isSpeech ? { output: () => audio.byteLength } : void 0,
2239
+ "ai.response.audio.mediaType": isSpeech ? { output: () => audio.mediaType } : void 0,
2240
+ "ai.response.audio.format": isSpeech && "format" in audio ? { output: () => audio.format } : void 0,
2241
+ ...getProviderUsageAttributes({
2242
+ usage: event.usage,
2243
+ prefix: "ai.usage"
2244
+ }),
2245
+ "ai.response.usage": event.usage == null ? void 0 : JSON.stringify(event.usage),
2246
+ "ai.response.providerMetadata": event.providerMetadata == null ? void 0 : JSON.stringify(event.providerMetadata)
2247
+ }));
2248
+ state.rootSpan.end();
2249
+ this.cleanupCallState(event.callId);
2250
+ }
2015
2251
  onGenerateEnd(event) {
2016
2252
  const state = this.getCallState(event.callId);
2017
2253
  if (!state?.rootSpan) return;