@@ -148,16 +148,7 @@ function ConversationMessages({
148148 streamingMsgId : string | null ;
149149 activeAction : string | null ;
150150} ) {
151- const streamingMessage =
152- ( streamingMsgId
153- ? messages . find ( ( message ) => message . id === streamingMsgId )
154- : null ) ?? null ;
155- const showPlanningNextMoves =
156- isStreaming &&
157- ! isReasoningStreaming &&
158- ! activeAction &&
159- Boolean ( streamingMessage ) &&
160- ! streamingMessage ?. content ;
151+ const showPlanningNextMoves = isStreaming && ! isReasoningStreaming && ! activeAction ;
161152
162153 return (
163154 < >
@@ -240,6 +231,36 @@ async function streamToWidget(
240231
241232 let fullText = "" ;
242233 let hasEmittedText = false ;
234+ let activeActionStartedAt = 0 ;
235+ let activeActionVersion = 0 ;
236+ let pendingActionClear : ReturnType < typeof setTimeout > | null = null ;
237+ const MIN_ACTION_VISIBLE_MS = 700 ;
238+
239+ function showAction ( action : string ) {
240+ activeActionVersion += 1 ;
241+ activeActionStartedAt = Date . now ( ) ;
242+ if ( pendingActionClear ) {
243+ clearTimeout ( pendingActionClear ) ;
244+ pendingActionClear = null ;
245+ }
246+ setCurrentAction ( widgetId , action ) ;
247+ }
248+
249+ function clearActionWithMinimumVisibility ( ) {
250+ const versionAtSchedule = activeActionVersion ;
251+ const elapsed = activeActionStartedAt ? Date . now ( ) - activeActionStartedAt : MIN_ACTION_VISIBLE_MS ;
252+ const delay = Math . max ( 0 , MIN_ACTION_VISIBLE_MS - elapsed ) ;
253+
254+ if ( pendingActionClear ) {
255+ clearTimeout ( pendingActionClear ) ;
256+ }
257+
258+ pendingActionClear = setTimeout ( ( ) => {
259+ pendingActionClear = null ;
260+ if ( activeActionVersion !== versionAtSchedule ) return ;
261+ setCurrentAction ( widgetId , null ) ;
262+ } , delay ) ;
263+ }
243264
244265 function startNewAssistantMessage ( ) {
245266 currentMsgId = nanoid ( ) ;
@@ -328,7 +349,7 @@ async function streamToWidget(
328349 } else if ( event . type === "widget-code" ) {
329350 if ( event . code ) {
330351 setWidgetCode ( widgetId , event . code ) ;
331- setCurrentAction ( widgetId , "Building widget…" ) ;
352+ showAction ( "Building widget…" ) ;
332353 setTimeout ( ( ) => bumpIframeVersion ( widgetId ) , 15000 ) ;
333354 }
334355 } else if ( event . type === "tool-call" ) {
@@ -355,9 +376,9 @@ async function streamToWidget(
355376 } else {
356377 action = `Using ${ event . toolName } ` ;
357378 }
358- if ( action ) setCurrentAction ( widgetId , action ) ;
379+ if ( action ) showAction ( action ) ;
359380 } else if ( event . type === "tool-result" ) {
360- setCurrentAction ( widgetId , null ) ;
381+ clearActionWithMinimumVisibility ( ) ;
361382 } else if ( event . type === "abort" ) {
362383 updateAssistantMessage (
363384 widgetId ,
@@ -384,6 +405,9 @@ async function streamToWidget(
384405 }
385406 } finally {
386407 abortControllers . delete ( widgetId ) ;
408+ if ( pendingActionClear ) {
409+ clearTimeout ( pendingActionClear ) ;
410+ }
387411 setCurrentAction ( widgetId , null ) ;
388412 setReasoningStreaming ( widgetId , false ) ;
389413 setStreaming ( widgetId , false ) ;
0 commit comments