@@ -51,7 +51,7 @@ public abstract class StreamTransformerBase(ILogger logger) : IStreamTransformer
5151 /// </summary>
5252 public string AgentProvider => GetAgentProvider ( ) ;
5353
54- public Task < Stream > TransformAsync ( Stream rawStream , Activity ? parentActivity , Cancel cancellationToken = default )
54+ public Task < Stream > TransformAsync ( Stream rawStream , string ? threadId , Activity ? parentActivity , Cancel cancellationToken = default )
5555 {
5656 // Configure pipe for low-latency streaming
5757 var pipeOptions = new PipeOptions (
@@ -70,7 +70,7 @@ public Task<Stream> TransformAsync(Stream rawStream, Activity? parentActivity, C
7070 // Note: We intentionally don't await this task as we need to return the stream immediately
7171 // The pipe handles synchronization and backpressure between producer and consumer
7272 // Pass parent activity - it will be disposed when streaming completes
73- _ = ProcessPipeAsync ( reader , pipe . Writer , parentActivity , cancellationToken ) ;
73+ _ = ProcessPipeAsync ( reader , pipe . Writer , threadId , parentActivity , cancellationToken ) ;
7474
7575 // Return the read side of the pipe as a stream
7676 return Task . FromResult ( pipe . Reader . AsStream ( ) ) ;
@@ -80,13 +80,13 @@ public Task<Stream> TransformAsync(Stream rawStream, Activity? parentActivity, C
8080 /// Process the pipe reader and write transformed events to the pipe writer.
8181 /// This runs concurrently with the consumer reading from the output stream.
8282 /// </summary>
83- private async Task ProcessPipeAsync ( PipeReader reader , PipeWriter writer , Activity ? parentActivity , CancellationToken cancellationToken )
83+ private async Task ProcessPipeAsync ( PipeReader reader , PipeWriter writer , string ? threadId , Activity ? parentActivity , CancellationToken cancellationToken )
8484 {
8585 try
8686 {
8787 try
8888 {
89- await ProcessStreamAsync ( reader , writer , parentActivity , cancellationToken ) ;
89+ await ProcessStreamAsync ( reader , writer , threadId , parentActivity , cancellationToken ) ;
9090 }
9191 catch ( OperationCanceledException ex )
9292 {
@@ -131,7 +131,7 @@ private async Task ProcessPipeAsync(PipeReader reader, PipeWriter writer, Activi
131131 /// Default implementation parses SSE events and JSON, then calls TransformJsonEvent.
132132 /// </summary>
133133 /// <returns>Stream processing result with metrics and captured output</returns>
134- private async Task ProcessStreamAsync ( PipeReader reader , PipeWriter writer , Activity ? parentActivity , CancellationToken cancellationToken )
134+ private async Task ProcessStreamAsync ( PipeReader reader , PipeWriter writer , string ? threadId , Activity ? parentActivity , CancellationToken cancellationToken )
135135 {
136136 using var activity = StreamTransformerActivitySource . StartActivity ( nameof ( ProcessStreamAsync ) ) ;
137137
@@ -141,7 +141,6 @@ private async Task ProcessStreamAsync(PipeReader reader, PipeWriter writer, Acti
141141 List < MessagePart > outputMessageParts = [ ] ;
142142 await foreach ( var sseEvent in ParseSseEventsAsync ( reader , cancellationToken ) )
143143 {
144- using var parseActivity = StreamTransformerActivitySource . StartActivity ( "AskAI Event" ) ;
145144 AskAiEvent ? transformedEvent ;
146145 try
147146 {
@@ -150,7 +149,7 @@ private async Task ProcessStreamAsync(PipeReader reader, PipeWriter writer, Acti
150149 var root = doc . RootElement ;
151150
152151 // Subclass transforms JsonElement to AskAiEvent
153- transformedEvent = TransformJsonEvent ( sseEvent . EventType , root ) ;
152+ transformedEvent = TransformJsonEvent ( threadId , sseEvent . EventType , root ) ;
154153 }
155154 catch ( JsonException ex )
156155 {
@@ -166,9 +165,11 @@ private async Task ProcessStreamAsync(PipeReader reader, PipeWriter writer, Acti
166165 continue ;
167166 }
168167
168+ using var parseActivity = StreamTransformerActivitySource . StartActivity ( "AskAI Event" ) ;
169+
169170 // Set event type tag on parse_event activity
170171 _ = parseActivity ? . SetTag ( "ask_ai.event.type" , transformedEvent . GetType ( ) . Name ) ;
171- _ = parseActivity ? . SetTag ( "gen_ai.respone .id" , transformedEvent . Id ) ;
172+ _ = parseActivity ? . SetTag ( "gen_ai.response .id" , transformedEvent . Id ) ;
172173
173174 switch ( transformedEvent )
174175 {
@@ -247,10 +248,11 @@ private async Task ProcessStreamAsync(PipeReader reader, PipeWriter writer, Acti
247248 /// Transform a parsed JSON event into an AskAiEvent.
248249 /// Subclasses implement provider-specific transformation logic.
249250 /// </summary>
251+ /// <param name="threadId">The conversation/thread ID, if available</param>
250252 /// <param name="eventType">The SSE event type (from "event:" field), or null if not present</param>
251253 /// <param name="json">The parsed JSON data from the "data:" field</param>
252254 /// <returns>The transformed AskAiEvent, or null to skip this event</returns>
253- protected abstract AskAiEvent ? TransformJsonEvent ( string ? eventType , JsonElement json ) ;
255+ protected abstract AskAiEvent ? TransformJsonEvent ( string ? threadId , string ? eventType , JsonElement json ) ;
254256
255257 /// <summary>
256258 /// Write a transformed event to the output stream
0 commit comments