@@ -81,4 +81,93 @@ public async Task<string> InvokeAgentAsync(string prompt, string? sessionId = nu
8181 }
8282 }
8383
84+ /// <summary>
85+ /// Invokes the AgentCore Runtime streaming agent and yields response chunks as they arrive via SSE.
86+ /// </summary>
87+ public async IAsyncEnumerable < string > InvokeAgentStreamingAsync (
88+ string prompt , string ? sessionId = null ,
89+ [ System . Runtime . CompilerServices . EnumeratorCancellation ] CancellationToken cancellationToken = default )
90+ {
91+ var arn = _settings . StreamingRuntimeArn ;
92+ if ( string . IsNullOrEmpty ( arn ) )
93+ {
94+ yield return "Error: StreamingRuntimeArn is not configured in appsettings.json" ;
95+ yield break ;
96+ }
97+
98+ _logger . LogInformation ( "Invoking streaming AgentCore Runtime: {Arn}" , arn ) ;
99+
100+ var payload = JsonSerializer . Serialize ( new { prompt } ) ;
101+ var payloadBytes = Encoding . UTF8 . GetBytes ( payload ) ;
102+
103+ var request = new InvokeAgentRuntimeRequest
104+ {
105+ AgentRuntimeArn = arn ,
106+ Payload = new MemoryStream ( payloadBytes ) ,
107+ ContentType = "application/json" ,
108+ Accept = "text/event-stream" ,
109+ } ;
110+
111+ if ( ! string . IsNullOrEmpty ( sessionId ) )
112+ {
113+ request . RuntimeSessionId = sessionId ;
114+ }
115+
116+ InvokeAgentRuntimeResponse ? response = null ;
117+ string ? invokeError = null ;
118+ try
119+ {
120+ response = await _client . InvokeAgentRuntimeAsync ( request , cancellationToken ) ;
121+ }
122+ catch ( Exception ex )
123+ {
124+ _logger . LogError ( ex , "Error invoking streaming AgentCore Runtime" ) ;
125+ invokeError = $ "Error: { ex . Message } ";
126+ }
127+
128+ if ( invokeError is not null )
129+ {
130+ yield return invokeError ;
131+ yield break ;
132+ }
133+
134+ using var reader = new StreamReader ( response ! . Response ) ;
135+ while ( true )
136+ {
137+ cancellationToken . ThrowIfCancellationRequested ( ) ;
138+
139+ var line = await reader . ReadLineAsync ( cancellationToken ) ;
140+ if ( line is null ) break ;
141+ if ( ! line . StartsWith ( "data: " ) ) continue ;
142+
143+ var json = line [ "data: " . Length ..] ;
144+ var chunk = ParseSseChunk ( json ) ;
145+
146+ if ( chunk is null ) break ; // "done" event
147+ if ( chunk . Length > 0 ) yield return chunk ;
148+ }
149+ }
150+
151+ /// <summary>
152+ /// Parses an SSE data payload. Returns the chunk text, empty string for skip, or null for "done".
153+ /// </summary>
154+ private string ? ParseSseChunk ( string json )
155+ {
156+ try
157+ {
158+ using var doc = JsonDocument . Parse ( json ) ;
159+
160+ if ( doc . RootElement . TryGetProperty ( "done" , out var doneProp ) && doneProp . GetBoolean ( ) )
161+ return null ;
162+
163+ if ( doc . RootElement . TryGetProperty ( "chunk" , out var chunkProp ) )
164+ return chunkProp . GetString ( ) ?? string . Empty ;
165+
166+ return string . Empty ;
167+ }
168+ catch ( JsonException )
169+ {
170+ return string . Empty ;
171+ }
172+ }
84173}
0 commit comments