@@ -191,13 +191,12 @@ private static async Task RunPromptWithCancelAfterTurnStartAsync(
191191 {
192192 using var cts = new CancellationTokenSource ( ) ;
193193 var runTask = runtime . RunPromptAsync ( request , cts . Token ) ;
194- await WaitForActiveTurnAsync ( runtime , runTask , workspacePath , CancellationToken . None ) . ConfigureAwait ( false ) ;
194+ await WaitForActiveTurnAsync ( runTask , workspacePath , CancellationToken . None ) . ConfigureAwait ( false ) ;
195195 cts . CancelAfter ( cancelAfter ) ;
196196 await runTask . ConfigureAwait ( false ) ;
197197 }
198198
199199 private static async Task WaitForActiveTurnAsync (
200- IConversationRuntime runtime ,
201200 Task runTask ,
202201 string workspacePath ,
203202 CancellationToken cancellationToken )
@@ -211,8 +210,7 @@ private static async Task WaitForActiveTurnAsync(
211210 throw new TimeoutException ( "The runtime completed before an active turn could be observed." ) ;
212211 }
213212
214- var latestSession = await runtime . GetLatestSessionAsync ( workspacePath , cancellationToken ) . ConfigureAwait ( false ) ;
215- if ( ! string . IsNullOrWhiteSpace ( latestSession ? . ActiveTurnId ) )
213+ if ( await HasTurnStartedEventAsync ( workspacePath , cancellationToken ) . ConfigureAwait ( false ) )
216214 {
217215 return ;
218216 }
@@ -223,6 +221,35 @@ private static async Task WaitForActiveTurnAsync(
223221 throw new TimeoutException ( "The runtime did not activate a turn before cancellation was requested." ) ;
224222 }
225223
224+ private static async Task < bool > HasTurnStartedEventAsync ( string workspacePath , CancellationToken cancellationToken )
225+ {
226+ var sessionsRoot = Path . Combine ( workspacePath , ".sharpclaw" , "sessions" ) ;
227+ if ( ! Directory . Exists ( sessionsRoot ) )
228+ {
229+ return false ;
230+ }
231+
232+ foreach ( var eventLogPath in Directory . EnumerateFiles ( sessionsRoot , "events.ndjson" , SearchOption . AllDirectories ) )
233+ {
234+ try
235+ {
236+ await using var stream = new FileStream ( eventLogPath , FileMode . Open , FileAccess . Read , FileShare . ReadWrite | FileShare . Delete ) ;
237+ using var reader = new StreamReader ( stream ) ;
238+ var content = await reader . ReadToEndAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
239+ if ( content . Contains ( "\" $eventType\" :\" turnStarted\" " , StringComparison . Ordinal ) )
240+ {
241+ return true ;
242+ }
243+ }
244+ catch ( IOException )
245+ {
246+ // The runtime may be appending the event concurrently; retry on the next poll.
247+ }
248+ }
249+
250+ return false ;
251+ }
252+
226253 private static string CreateTemporaryWorkspace ( )
227254 {
228255 var workspacePath = Path . Combine ( Path . GetTempPath ( ) , "sharpclaw-tests" , Guid . NewGuid ( ) . ToString ( "N" ) ) ;
0 commit comments