@ai-sdk/otel 1.0.0-beta.55 → 1.0.0-beta.58

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.
@@ -1,5 +1,3 @@
1
- import { LanguageModelV4Prompt } from '@ai-sdk/provider';
2
- import type { Context as AISDKContext } from '@ai-sdk/provider-utils';
3
1
  import {
4
2
  Attributes,
5
3
  AttributeValue,
@@ -12,27 +10,29 @@ import {
12
10
  Tracer,
13
11
  } from '@opentelemetry/api';
14
12
  import type {
15
- EmbedFinishEvent,
16
- EmbedOnFinishEvent,
17
- EmbedOnStartEvent,
13
+ EmbeddingModelCallEndEvent,
14
+ EmbedEndEvent,
18
15
  EmbedStartEvent,
19
- ObjectOnFinishEvent,
20
- ObjectOnStartEvent,
21
- ObjectOnStepFinishEvent,
22
- ObjectOnStepStartEvent,
23
- OnChunkEvent,
24
- OnFinishEvent,
25
- OnStartEvent,
26
- OnStepFinishEvent,
27
- OnStepStartEvent,
16
+ LanguageModelCallEndEvent,
17
+ LanguageModelCallStartEvent,
18
+ EmbeddingModelCallStartEvent,
19
+ GenerateObjectEndEvent,
20
+ GenerateObjectStartEvent,
21
+ GenerateObjectStepEndEvent,
22
+ GenerateObjectStepStartEvent,
23
+ StreamTextChunkEvent,
24
+ GenerateTextEndEvent,
25
+ GenerateTextStartEvent,
26
+ GenerateTextStepEndEvent,
27
+ GenerateTextStepStartEvent,
28
28
  ToolExecutionEndEvent,
29
29
  ToolExecutionStartEvent,
30
- OutputInterface as Output,
31
- RerankFinishEvent,
32
- RerankOnFinishEvent,
33
- RerankOnStartEvent,
30
+ RerankingModelCallEndEvent,
31
+ RerankEndEvent,
34
32
  RerankStartEvent,
35
- TelemetryIntegration,
33
+ RerankingModelCallStartEvent,
34
+ InferTelemetryEvent,
35
+ Telemetry,
36
36
  TelemetryOptions,
37
37
  ToolSet,
38
38
  } from 'ai';
@@ -115,16 +115,6 @@ function selectAttributes(
115
115
  return result;
116
116
  }
117
117
 
118
- interface OtelStepStartEvent<
119
- TOOLS extends ToolSet = ToolSet,
120
- RUNTIME_CONTEXT extends AISDKContext = AISDKContext,
121
- OUTPUT extends Output = Output,
122
- > extends OnStepStartEvent<TOOLS, RUNTIME_CONTEXT, OUTPUT> {
123
- readonly promptMessages?: LanguageModelV4Prompt;
124
- readonly stepTools?: ReadonlyArray<Record<string, unknown>>;
125
- readonly stepToolChoice?: unknown;
126
- }
127
-
128
118
  interface CallState {
129
119
  operationId: string;
130
120
  telemetry: TelemetryOptions | undefined;
@@ -132,6 +122,8 @@ interface CallState {
132
122
  rootContext: OpenTelemetryContext | undefined;
133
123
  stepSpan: Span | undefined;
134
124
  stepContext: OpenTelemetryContext | undefined;
125
+ inferenceSpan: Span | undefined;
126
+ inferenceContext: OpenTelemetryContext | undefined;
135
127
  embedSpans: Map<string, { span: Span; context: OpenTelemetryContext }>;
136
128
  rerankSpan: { span: Span; context: OpenTelemetryContext } | undefined;
137
129
  toolSpans: Map<string, { span: Span; context: OpenTelemetryContext }>;
@@ -140,7 +132,7 @@ interface CallState {
140
132
  modelId: string;
141
133
  }
142
134
 
143
- export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
135
+ export class OpenTelemetry implements Telemetry {
144
136
  private readonly callStates = new Map<string, CallState>();
145
137
 
146
138
  private readonly tracer: Tracer;
@@ -181,23 +173,23 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
181
173
 
182
174
  onStart(
183
175
  event:
184
- | OnStartEvent
185
- | ObjectOnStartEvent
186
- | EmbedOnStartEvent
187
- | RerankOnStartEvent,
176
+ | InferTelemetryEvent<GenerateTextStartEvent>
177
+ | InferTelemetryEvent<GenerateObjectStartEvent>
178
+ | InferTelemetryEvent<EmbedStartEvent>
179
+ | InferTelemetryEvent<RerankStartEvent>,
188
180
  ): void {
189
- if (event.isEnabled === false) return;
190
-
191
181
  if (
192
182
  event.operationId === 'ai.embed' ||
193
183
  event.operationId === 'ai.embedMany'
194
184
  ) {
195
- this.onEmbedOperationStart(event as EmbedOnStartEvent);
185
+ this.onEmbedOperationStart(event as InferTelemetryEvent<EmbedStartEvent>);
196
186
  return;
197
187
  }
198
188
 
199
189
  if (event.operationId === 'ai.rerank') {
200
- this.onRerankOperationStart(event as RerankOnStartEvent);
190
+ this.onRerankOperationStart(
191
+ event as InferTelemetryEvent<RerankStartEvent>,
192
+ );
201
193
  return;
202
194
  }
203
195
 
@@ -205,16 +197,19 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
205
197
  event.operationId === 'ai.generateObject' ||
206
198
  event.operationId === 'ai.streamObject'
207
199
  ) {
208
- this.onObjectOperationStart(event as ObjectOnStartEvent);
200
+ this.onObjectOperationStart(
201
+ event as InferTelemetryEvent<GenerateObjectStartEvent>,
202
+ );
209
203
  return;
210
204
  }
211
205
 
212
- this.onGenerateStart(event as OnStartEvent);
206
+ this.onGenerateStart(event as InferTelemetryEvent<GenerateTextStartEvent>);
213
207
  }
214
208
 
215
- private onGenerateStart(event: OnStartEvent): void {
209
+ private onGenerateStart(
210
+ event: InferTelemetryEvent<GenerateTextStartEvent>,
211
+ ): void {
216
212
  const telemetry: TelemetryOptions = {
217
- isEnabled: event.isEnabled,
218
213
  recordInputs: event.recordInputs,
219
214
  recordOutputs: event.recordOutputs,
220
215
  functionId: event.functionId,
@@ -260,7 +255,7 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
260
255
  input: () =>
261
256
  JSON.stringify(
262
257
  formatModelMessages({
263
- prompt: event.prompt,
258
+ prompt: undefined,
264
259
  messages: event.messages,
265
260
  }),
266
261
  ),
@@ -281,6 +276,8 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
281
276
  rootContext,
282
277
  stepSpan: undefined,
283
278
  stepContext: undefined,
279
+ inferenceSpan: undefined,
280
+ inferenceContext: undefined,
284
281
  embedSpans: new Map(),
285
282
  rerankSpan: undefined,
286
283
  toolSpans: new Map(),
@@ -290,9 +287,10 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
290
287
  });
291
288
  }
292
289
 
293
- private onObjectOperationStart(event: ObjectOnStartEvent): void {
290
+ private onObjectOperationStart(
291
+ event: InferTelemetryEvent<GenerateObjectStartEvent>,
292
+ ): void {
294
293
  const telemetry: TelemetryOptions = {
295
- isEnabled: event.isEnabled,
296
294
  recordInputs: event.recordInputs,
297
295
  recordOutputs: event.recordOutputs,
298
296
  functionId: event.functionId,
@@ -358,6 +356,8 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
358
356
  rootContext,
359
357
  stepSpan: undefined,
360
358
  stepContext: undefined,
359
+ inferenceSpan: undefined,
360
+ inferenceContext: undefined,
361
361
  embedSpans: new Map(),
362
362
  rerankSpan: undefined,
363
363
  toolSpans: new Map(),
@@ -368,7 +368,7 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
368
368
  }
369
369
 
370
370
  /** @deprecated */
371
- onObjectStepStart(event: ObjectOnStepStartEvent): void {
371
+ onObjectStepStart(event: GenerateObjectStepStartEvent): void {
372
372
  const state = this.getCallState(event.callId);
373
373
  if (!state?.rootSpan || !state.rootContext) return;
374
374
 
@@ -403,22 +403,25 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
403
403
  });
404
404
 
405
405
  const spanName = `chat ${event.modelId}`;
406
- state.stepSpan = this.tracer.startSpan(
406
+ state.inferenceSpan = this.tracer.startSpan(
407
407
  spanName,
408
408
  { attributes, kind: SpanKind.CLIENT },
409
409
  state.rootContext,
410
410
  );
411
- state.stepContext = trace.setSpan(state.rootContext, state.stepSpan);
411
+ state.inferenceContext = trace.setSpan(
412
+ state.rootContext,
413
+ state.inferenceSpan,
414
+ );
412
415
  }
413
416
 
414
417
  /** @deprecated */
415
- onObjectStepFinish(event: ObjectOnStepFinishEvent): void {
418
+ onObjectStepFinish(event: GenerateObjectStepEndEvent): void {
416
419
  const state = this.getCallState(event.callId);
417
- if (!state?.stepSpan) return;
420
+ if (!state?.inferenceSpan) return;
418
421
 
419
422
  const { telemetry } = state;
420
423
 
421
- state.stepSpan.setAttributes(
424
+ state.inferenceSpan.setAttributes(
422
425
  selectAttributes(telemetry, {
423
426
  'gen_ai.response.finish_reasons': [event.finishReason],
424
427
  'gen_ai.response.id': event.response.id,
@@ -443,14 +446,15 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
443
446
  }),
444
447
  );
445
448
 
446
- state.stepSpan.end();
447
- state.stepSpan = undefined;
448
- state.stepContext = undefined;
449
+ state.inferenceSpan.end();
450
+ state.inferenceSpan = undefined;
451
+ state.inferenceContext = undefined;
449
452
  }
450
453
 
451
- private onEmbedOperationStart(event: EmbedOnStartEvent): void {
454
+ private onEmbedOperationStart(
455
+ event: InferTelemetryEvent<EmbedStartEvent>,
456
+ ): void {
452
457
  const telemetry: TelemetryOptions = {
453
- isEnabled: event.isEnabled,
454
458
  recordInputs: event.recordInputs,
455
459
  recordOutputs: event.recordOutputs,
456
460
  functionId: event.functionId,
@@ -482,6 +486,8 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
482
486
  rootContext,
483
487
  stepSpan: undefined,
484
488
  stepContext: undefined,
489
+ inferenceSpan: undefined,
490
+ inferenceContext: undefined,
485
491
  embedSpans: new Map(),
486
492
  rerankSpan: undefined,
487
493
  toolSpans: new Map(),
@@ -491,14 +497,31 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
491
497
  });
492
498
  }
493
499
 
494
- onStepStart(event: OtelStepStartEvent): void {
500
+ onStepStart(event: GenerateTextStepStartEvent<ToolSet>): void {
495
501
  const state = this.getCallState(event.callId);
496
502
  if (!state?.rootSpan || !state.rootContext) return;
497
503
 
504
+ const { telemetry } = state;
505
+ const stepAttributes = selectAttributes(telemetry, {
506
+ 'gen_ai.operation.name': 'agent_step',
507
+ });
508
+
509
+ state.stepSpan = this.tracer.startSpan(
510
+ `step ${event.steps.length + 1}`,
511
+ { attributes: stepAttributes, kind: SpanKind.INTERNAL },
512
+ state.rootContext,
513
+ );
514
+ state.stepContext = trace.setSpan(state.rootContext, state.stepSpan);
515
+ }
516
+
517
+ onLanguageModelCallStart(event: LanguageModelCallStartEvent): void {
518
+ const state = this.getCallState(event.callId);
519
+ if (!state?.stepContext) return;
520
+
498
521
  const { telemetry } = state;
499
522
  const providerName = mapProviderName(event.provider);
500
523
 
501
- const attributes = selectAttributes(telemetry, {
524
+ const inferenceAttributes = selectAttributes(telemetry, {
502
525
  'gen_ai.operation.name': 'chat',
503
526
  'gen_ai.provider.name': providerName,
504
527
  'gen_ai.request.model': event.modelId,
@@ -520,24 +543,74 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
520
543
  'gen_ai.request.top_k': state.settings.topK as number | undefined,
521
544
  'gen_ai.request.top_p': state.settings.topP as number | undefined,
522
545
  'gen_ai.input.messages': {
523
- input: () =>
524
- event.promptMessages
525
- ? JSON.stringify(formatInputMessages(event.promptMessages))
526
- : undefined,
546
+ input: () => {
547
+ const formattedMessages = formatModelMessages({
548
+ prompt: undefined,
549
+ messages: event.messages,
550
+ });
551
+
552
+ return formattedMessages.length > 0
553
+ ? JSON.stringify(formattedMessages)
554
+ : undefined;
555
+ },
527
556
  },
528
557
  'gen_ai.tool.definitions': {
529
- input: () =>
530
- event.stepTools ? JSON.stringify(event.stepTools) : undefined,
558
+ input: () => (event.tools ? JSON.stringify(event.tools) : undefined),
531
559
  },
532
560
  });
533
561
 
534
- const spanName = `chat ${event.modelId}`;
535
- state.stepSpan = this.tracer.startSpan(
536
- spanName,
537
- { attributes, kind: SpanKind.CLIENT },
538
- state.rootContext,
562
+ state.inferenceSpan = this.tracer.startSpan(
563
+ `chat ${event.modelId}`,
564
+ { attributes: inferenceAttributes, kind: SpanKind.CLIENT },
565
+ state.stepContext,
566
+ );
567
+ state.inferenceContext = trace.setSpan(
568
+ state.stepContext,
569
+ state.inferenceSpan,
539
570
  );
540
- state.stepContext = trace.setSpan(state.rootContext, state.stepSpan);
571
+ }
572
+
573
+ onLanguageModelCallEnd(event: LanguageModelCallEndEvent<ToolSet>): void {
574
+ const state = this.getCallState(event.callId);
575
+ if (!state?.inferenceSpan) return;
576
+
577
+ const { telemetry } = state;
578
+
579
+ state.inferenceSpan.setAttributes(
580
+ selectAttributes(telemetry, {
581
+ 'gen_ai.response.finish_reasons': [event.finishReason],
582
+ 'gen_ai.response.id': event.responseId,
583
+ 'gen_ai.usage.input_tokens': event.usage.inputTokens,
584
+ 'gen_ai.usage.output_tokens': event.usage.outputTokens,
585
+ 'gen_ai.usage.cache_read.input_tokens':
586
+ event.usage.inputTokenDetails?.cacheReadTokens ??
587
+ event.usage.cachedInputTokens,
588
+ 'gen_ai.usage.cache_creation.input_tokens':
589
+ event.usage.inputTokenDetails?.cacheWriteTokens,
590
+ 'gen_ai.output.messages': {
591
+ output: () =>
592
+ JSON.stringify(
593
+ formatOutputMessages({
594
+ text:
595
+ event.content
596
+ .filter(p => p.type === 'text')
597
+ .map(p => p.text)
598
+ .join('') || undefined,
599
+ reasoning: event.content.filter(p => p.type === 'reasoning'),
600
+ toolCalls: event.content.filter(p => p.type === 'tool-call'),
601
+ files: event.content
602
+ .filter(p => p.type === 'file')
603
+ .map(p => p.file),
604
+ finishReason: event.finishReason,
605
+ }),
606
+ ),
607
+ },
608
+ }),
609
+ );
610
+
611
+ state.inferenceSpan.end();
612
+ state.inferenceSpan = undefined;
613
+ state.inferenceContext = undefined;
541
614
  }
542
615
 
543
616
  onToolExecutionStart(event: ToolExecutionStartEvent<ToolSet>): void {
@@ -581,12 +654,13 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
581
654
  const { span } = toolSpanEntry;
582
655
  const { telemetry } = state;
583
656
 
584
- if (event.success) {
657
+ const { toolOutput } = event;
658
+ if (toolOutput.type === 'tool-result') {
585
659
  try {
586
660
  span.setAttributes(
587
661
  selectAttributes(telemetry, {
588
662
  'gen_ai.tool.call.result': {
589
- output: () => JSON.stringify(event.output),
663
+ output: () => JSON.stringify(toolOutput.output),
590
664
  },
591
665
  }),
592
666
  );
@@ -594,46 +668,17 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
594
668
  // JSON.stringify might fail for non-serializable results
595
669
  }
596
670
  } else {
597
- recordSpanError(span, event.error);
671
+ recordSpanError(span, toolOutput.error);
598
672
  }
599
673
 
600
674
  span.end();
601
675
  state.toolSpans.delete(event.toolCall.toolCallId);
602
676
  }
603
677
 
604
- onStepFinish(event: OnStepFinishEvent<ToolSet>): void {
678
+ onStepFinish(event: GenerateTextStepEndEvent<ToolSet>): void {
605
679
  const state = this.getCallState(event.callId);
606
680
  if (!state?.stepSpan) return;
607
681
 
608
- const { telemetry } = state;
609
-
610
- state.stepSpan.setAttributes(
611
- selectAttributes(telemetry, {
612
- 'gen_ai.response.finish_reasons': [event.finishReason],
613
- 'gen_ai.response.id': event.response.id,
614
- 'gen_ai.response.model': event.response.modelId,
615
- 'gen_ai.usage.input_tokens': event.usage.inputTokens,
616
- 'gen_ai.usage.output_tokens': event.usage.outputTokens,
617
- 'gen_ai.usage.cache_read.input_tokens':
618
- event.usage.inputTokenDetails?.cacheReadTokens ??
619
- event.usage.cachedInputTokens,
620
- 'gen_ai.usage.cache_creation.input_tokens':
621
- event.usage.inputTokenDetails?.cacheWriteTokens,
622
- 'gen_ai.output.messages': {
623
- output: () =>
624
- JSON.stringify(
625
- formatOutputMessages({
626
- text: event.text ?? undefined,
627
- reasoning: event.reasoning as ReadonlyArray<{ text?: string }>,
628
- toolCalls: event.toolCalls,
629
- files: event.files,
630
- finishReason: event.finishReason,
631
- }),
632
- ),
633
- },
634
- }),
635
- );
636
-
637
682
  state.stepSpan.end();
638
683
  state.stepSpan = undefined;
639
684
  state.stepContext = undefined;
@@ -641,10 +686,10 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
641
686
 
642
687
  onFinish(
643
688
  event:
644
- | OnFinishEvent<ToolSet>
645
- | ObjectOnFinishEvent<unknown>
646
- | EmbedOnFinishEvent
647
- | RerankOnFinishEvent,
689
+ | GenerateTextEndEvent<ToolSet>
690
+ | GenerateObjectEndEvent<unknown>
691
+ | EmbedEndEvent
692
+ | RerankEndEvent,
648
693
  ): void {
649
694
  const state = this.getCallState(event.callId);
650
695
  if (!state?.rootSpan) return;
@@ -653,12 +698,12 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
653
698
  state.operationId === 'ai.embed' ||
654
699
  state.operationId === 'ai.embedMany'
655
700
  ) {
656
- this.onEmbedOperationFinish(event as EmbedOnFinishEvent);
701
+ this.onEmbedOperationFinish(event as EmbedEndEvent);
657
702
  return;
658
703
  }
659
704
 
660
705
  if (state.operationId === 'ai.rerank') {
661
- this.onRerankOperationFinish(event as RerankOnFinishEvent);
706
+ this.onRerankOperationFinish(event as RerankEndEvent);
662
707
  return;
663
708
  }
664
709
 
@@ -666,14 +711,14 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
666
711
  state.operationId === 'ai.generateObject' ||
667
712
  state.operationId === 'ai.streamObject'
668
713
  ) {
669
- this.onObjectOperationFinish(event as ObjectOnFinishEvent<unknown>);
714
+ this.onObjectOperationFinish(event as GenerateObjectEndEvent<unknown>);
670
715
  return;
671
716
  }
672
717
 
673
- this.onGenerateFinish(event as OnFinishEvent<ToolSet>);
718
+ this.onGenerateFinish(event as GenerateTextEndEvent<ToolSet>);
674
719
  }
675
720
 
676
- private onGenerateFinish(event: OnFinishEvent<ToolSet>): void {
721
+ private onGenerateFinish(event: GenerateTextEndEvent<ToolSet>): void {
677
722
  const state = this.getCallState(event.callId);
678
723
  if (!state?.rootSpan) return;
679
724
 
@@ -708,7 +753,9 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
708
753
  this.cleanupCallState(event.callId);
709
754
  }
710
755
 
711
- private onObjectOperationFinish(event: ObjectOnFinishEvent<unknown>): void {
756
+ private onObjectOperationFinish(
757
+ event: GenerateObjectEndEvent<unknown>,
758
+ ): void {
712
759
  const state = this.getCallState(event.callId);
713
760
  if (!state?.rootSpan) return;
714
761
 
@@ -738,7 +785,7 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
738
785
  this.cleanupCallState(event.callId);
739
786
  }
740
787
 
741
- private onEmbedOperationFinish(event: EmbedOnFinishEvent): void {
788
+ private onEmbedOperationFinish(event: EmbedEndEvent): void {
742
789
  const state = this.getCallState(event.callId);
743
790
  if (!state?.rootSpan) return;
744
791
 
@@ -754,7 +801,7 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
754
801
  this.cleanupCallState(event.callId);
755
802
  }
756
803
 
757
- onEmbedStart(event: EmbedStartEvent): void {
804
+ onEmbedStart(event: EmbeddingModelCallStartEvent): void {
758
805
  const state = this.getCallState(event.callId);
759
806
  if (!state?.rootSpan || !state.rootContext) return;
760
807
 
@@ -781,7 +828,7 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
781
828
  });
782
829
  }
783
830
 
784
- onEmbedFinish(event: EmbedFinishEvent): void {
831
+ onEmbedFinish(event: EmbeddingModelCallEndEvent): void {
785
832
  const state = this.getCallState(event.callId);
786
833
  if (!state) return;
787
834
 
@@ -801,9 +848,10 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
801
848
  state.embedSpans.delete(event.embedCallId);
802
849
  }
803
850
 
804
- private onRerankOperationStart(event: RerankOnStartEvent): void {
851
+ private onRerankOperationStart(
852
+ event: InferTelemetryEvent<RerankStartEvent>,
853
+ ): void {
805
854
  const telemetry: TelemetryOptions = {
806
- isEnabled: event.isEnabled,
807
855
  recordInputs: event.recordInputs,
808
856
  recordOutputs: event.recordOutputs,
809
857
  functionId: event.functionId,
@@ -835,6 +883,8 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
835
883
  rootContext,
836
884
  stepSpan: undefined,
837
885
  stepContext: undefined,
886
+ inferenceSpan: undefined,
887
+ inferenceContext: undefined,
838
888
  embedSpans: new Map(),
839
889
  rerankSpan: undefined,
840
890
  toolSpans: new Map(),
@@ -844,7 +894,7 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
844
894
  });
845
895
  }
846
896
 
847
- private onRerankOperationFinish(event: RerankOnFinishEvent): void {
897
+ private onRerankOperationFinish(event: RerankEndEvent): void {
848
898
  const state = this.getCallState(event.callId);
849
899
  if (!state?.rootSpan) return;
850
900
 
@@ -852,7 +902,7 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
852
902
  this.cleanupCallState(event.callId);
853
903
  }
854
904
 
855
- onRerankStart(event: RerankStartEvent): void {
905
+ onRerankStart(event: RerankingModelCallStartEvent): void {
856
906
  const state = this.getCallState(event.callId);
857
907
  if (!state?.rootSpan || !state.rootContext) return;
858
908
 
@@ -876,7 +926,7 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
876
926
  state.rerankSpan = { span: rerankSpan, context: rerankContext };
877
927
  }
878
928
 
879
- onRerankFinish(event: RerankFinishEvent): void {
929
+ onRerankFinish(event: RerankingModelCallEndEvent): void {
880
930
  const state = this.getCallState(event.callId);
881
931
  if (!state?.rerankSpan) return;
882
932
 
@@ -886,7 +936,7 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
886
936
  state.rerankSpan = undefined;
887
937
  }
888
938
 
889
- onChunk(_event: OnChunkEvent<ToolSet>): void {
939
+ onChunk(_event: StreamTextChunkEvent<ToolSet>): void {
890
940
  // No-op: streaming chunk events are not part of the GenAI SemConv.
891
941
  }
892
942
 
@@ -899,9 +949,24 @@ export class GenAIOpenTelemetryIntegration implements TelemetryIntegration {
899
949
 
900
950
  const actualError = event.error ?? error;
901
951
 
952
+ for (const { span: toolSpan } of state.toolSpans.values()) {
953
+ recordSpanError(toolSpan, actualError);
954
+ toolSpan.end();
955
+ }
956
+ state.toolSpans.clear();
957
+
958
+ if (state.inferenceSpan) {
959
+ recordSpanError(state.inferenceSpan, actualError);
960
+ state.inferenceSpan.end();
961
+ state.inferenceSpan = undefined;
962
+ state.inferenceContext = undefined;
963
+ }
964
+
902
965
  if (state.stepSpan) {
903
966
  recordSpanError(state.stepSpan, actualError);
904
967
  state.stepSpan.end();
968
+ state.stepSpan = undefined;
969
+ state.stepContext = undefined;
905
970
  }
906
971
 
907
972
  for (const { span: embedSpan } of state.embedSpans.values()) {