@@ -351,7 +351,6 @@ export function useChat(
351351 } )
352352 setActiveResourceId ( resource . id )
353353
354- // Ephemeral UI tab — must not be stored; it would reappear as "Writing file..." after refresh.
355354 if ( resource . id === 'streaming-file' ) {
356355 return true
357356 }
@@ -795,18 +794,42 @@ export function useChat(
795794 prev = { fileName : '' , content : '' }
796795 streamingFileRef . current = prev
797796 setStreamingFile ( prev )
798- if ( toolName === 'workspace_file' && activeSubagent !== 'file_write' ) {
799- addResource ( { type : 'file' , id : 'streaming-file' , title : 'Writing file...' } )
800- }
801797 }
802798 const raw = prev . content + delta
803799 let fileName = prev . fileName
804800 if ( ! fileName ) {
805801 const m = raw . match ( / " f i l e N a m e " \s * : \s * " ( [ ^ " ] + ) " / )
806802 if ( m ) {
807803 fileName = m [ 1 ]
804+ }
805+ }
806+ const fileIdMatch = raw . match ( / " f i l e I d " \s * : \s * " ( [ ^ " ] + ) " / )
807+ const matchedResourceId = fileIdMatch ?. [ 1 ]
808+ if (
809+ matchedResourceId &&
810+ resourcesRef . current . some (
811+ ( resource ) => resource . type === 'file' && resource . id === matchedResourceId
812+ )
813+ ) {
814+ setActiveResourceId ( matchedResourceId )
815+ setResources ( ( rs ) => rs . filter ( ( resource ) => resource . id !== 'streaming-file' ) )
816+ } else if ( fileName || fileIdMatch ) {
817+ const hasStreamingResource = resourcesRef . current . some (
818+ ( resource ) => resource . id === 'streaming-file'
819+ )
820+ if ( ! hasStreamingResource ) {
821+ addResource ( {
822+ type : 'file' ,
823+ id : 'streaming-file' ,
824+ title : fileName || 'Writing file...' ,
825+ } )
826+ } else if ( fileName ) {
808827 setResources ( ( rs ) =>
809- rs . map ( ( r ) => ( r . id === 'streaming-file' ? { ...r , title : fileName } : r ) )
828+ rs . map ( ( resource ) =>
829+ resource . id === 'streaming-file'
830+ ? { ...resource , title : fileName }
831+ : resource
832+ )
810833 )
811834 }
812835 }
@@ -917,8 +940,9 @@ export function useChat(
917940 if ( fileResource ) {
918941 setResources ( ( rs ) => {
919942 const without = rs . filter ( ( r ) => r . id !== 'streaming-file' )
920- if ( without . some ( ( r ) => r . type === 'file' && r . id === fileResource . id ) )
943+ if ( without . some ( ( r ) => r . type === 'file' && r . id === fileResource . id ) ) {
921944 return without
945+ }
922946 return [ ...without , fileResource ]
923947 } )
924948 setActiveResourceId ( fileResource . id )
@@ -1029,7 +1053,6 @@ export function useChat(
10291053 // re-renders after setStreamingFile, and the handler only appends when prev exists.
10301054 streamingFileRef . current = emptyFile
10311055 setStreamingFile ( emptyFile )
1032- addResource ( { type : 'file' , id : 'streaming-file' , title : 'Writing file...' } )
10331056 }
10341057 flush ( )
10351058 }
@@ -1335,6 +1358,9 @@ export function useChat(
13351358 body : JSON . stringify ( { streamId : sid } ) ,
13361359 } ) . catch ( ( ) => { } )
13371360 }
1361+ setStreamingFile ( null )
1362+ streamingFileRef . current = null
1363+ setResources ( ( rs ) => rs . filter ( ( resource ) => resource . id !== 'streaming-file' ) )
13381364
13391365 setMessages ( ( prev ) =>
13401366 prev . map ( ( msg ) => {
0 commit comments