@@ -354,6 +354,7 @@ export function useChat(
354354 streamingFileRef . current = streamingFile
355355 const filePreviewSessionsRef = useRef < Map < string , StreamingFilePreview > > ( new Map ( ) )
356356 const activeFilePreviewToolCallIdRef = useRef < string | null > ( null )
357+ const editContentParentToolCallIdRef = useRef < Map < string , string > > ( new Map ( ) )
357358
358359 const [ messageQueue , setMessageQueue ] = useState < QueuedMessage [ ] > ( [ ] )
359360 const messageQueueRef = useRef < QueuedMessage [ ] > ( [ ] )
@@ -368,6 +369,15 @@ export function useChat(
368369 options ?: { preserveExistingState ?: boolean }
369370 ) => Promise < { sawStreamError : boolean ; sawComplete : boolean } >
370371 > ( async ( ) => ( { sawStreamError : false , sawComplete : false } ) )
372+ const attachToExistingStreamRef = useRef <
373+ ( opts : {
374+ streamId : string
375+ assistantId : string
376+ expectedGen : number
377+ initialBatch ?: StreamBatchResponse | null
378+ afterCursor ?: string
379+ } ) => Promise < { error : boolean ; aborted : boolean } >
380+ > ( async ( ) => ( { error : false , aborted : true } ) )
371381 const retryReconnectRef = useRef <
372382 ( opts : { streamId : string ; assistantId : string ; gen : number } ) => Promise < boolean >
373383 > ( async ( ) => false )
@@ -518,6 +528,7 @@ export function useChat(
518528 streamingFileRef . current = null
519529 filePreviewSessionsRef . current . clear ( )
520530 activeFilePreviewToolCallIdRef . current = null
531+ editContentParentToolCallIdRef . current . clear ( )
521532 setMessageQueue ( [ ] )
522533 } , [ initialChatId , queryClient ] )
523534
@@ -541,6 +552,7 @@ export function useChat(
541552 streamingFileRef . current = null
542553 filePreviewSessionsRef . current . clear ( )
543554 activeFilePreviewToolCallIdRef . current = null
555+ editContentParentToolCallIdRef . current . clear ( )
544556 setMessageQueue ( [ ] )
545557 } , [ isHomePage ] )
546558
@@ -617,7 +629,7 @@ export function useChat(
617629
618630 const reconnectResult =
619631 snapshotEvents . length > 0
620- ? await attachToExistingStream ( {
632+ ? await attachToExistingStreamRef . current ( {
621633 streamId : activeStreamId ,
622634 assistantId,
623635 expectedGen : gen ,
@@ -1015,6 +1027,10 @@ export function useChat(
10151027 sessions . set ( id , nextSession )
10161028 activeFilePreviewToolCallIdRef . current = id
10171029 streamingFileRef . current = nextSession
1030+ const previewToolIdx = toolMap . get ( id )
1031+ if ( previewToolIdx !== undefined && blocks [ previewToolIdx ] . toolCall ) {
1032+ blocks [ previewToolIdx ] . toolCall ! . status = 'executing'
1033+ }
10181034 setStreamingFile ( nextSession )
10191035 break
10201036 }
@@ -1062,11 +1078,19 @@ export function useChat(
10621078 const opMatch = tc . streamingArgs . match ( / " o p e r a t i o n " \s * : \s * " ( \w + ) " / )
10631079 const op = opMatch ?. [ 1 ] ?? ''
10641080 const verb =
1065- op === 'patch' || op === 'update' || op === 'rename'
1066- ? 'Editing'
1067- : op === 'delete'
1068- ? 'Deleting'
1069- : 'Writing'
1081+ op === 'create'
1082+ ? 'Creating'
1083+ : op === 'append'
1084+ ? 'Adding'
1085+ : op === 'patch'
1086+ ? 'Editing'
1087+ : op === 'update'
1088+ ? 'Writing'
1089+ : op === 'rename'
1090+ ? 'Renaming'
1091+ : op === 'delete'
1092+ ? 'Deleting'
1093+ : 'Writing'
10701094 const titleMatch = tc . streamingArgs . match ( / " t i t l e " \s * : \s * " ( [ ^ " ] * ) " / )
10711095 if ( titleMatch ?. [ 1 ] ) {
10721096 const unescaped = titleMatch [ 1 ]
@@ -1174,7 +1198,20 @@ export function useChat(
11741198 clientExecutionStartedRef . current . delete ( id )
11751199 }
11761200
1177- if ( tc . name === WorkspaceFile . id ) {
1201+ const workspaceFileOperation =
1202+ tc . name === WorkspaceFile . id && typeof tc . params ?. operation === 'string'
1203+ ? tc . params . operation
1204+ : undefined
1205+ const shouldKeepWorkspacePreviewOpen =
1206+ tc . name === WorkspaceFile . id &&
1207+ ( workspaceFileOperation === 'append' ||
1208+ workspaceFileOperation === 'update' ||
1209+ workspaceFileOperation === 'patch' )
1210+
1211+ if (
1212+ ( tc . name === WorkspaceFile . id || tc . name === 'edit_content' ) &&
1213+ ! shouldKeepWorkspacePreviewOpen
1214+ ) {
11781215 filePreviewSessionsRef . current . delete ( id )
11791216 if ( activeFilePreviewToolCallIdRef . current === id ) {
11801217 activeFilePreviewToolCallIdRef . current = null
@@ -1198,6 +1235,7 @@ export function useChat(
11981235 setResources ( ( rs ) => rs . filter ( ( r ) => r . id !== 'streaming-file' ) )
11991236 }
12001237 }
1238+ editContentParentToolCallIdRef . current . delete ( id )
12011239 break
12021240 }
12031241
@@ -1222,11 +1260,19 @@ export function useChat(
12221260 if ( name === WorkspaceFile . id ) {
12231261 const operation = typeof args ?. operation === 'string' ? args . operation : ''
12241262 const verb =
1225- operation === 'patch' || operation === 'update' || operation === 'rename'
1226- ? 'Editing'
1227- : operation === 'delete'
1228- ? 'Deleting'
1229- : 'Writing'
1263+ operation === 'create'
1264+ ? 'Creating'
1265+ : operation === 'append'
1266+ ? 'Adding'
1267+ : operation === 'patch'
1268+ ? 'Editing'
1269+ : operation === 'update'
1270+ ? 'Writing'
1271+ : operation === 'rename'
1272+ ? 'Renaming'
1273+ : operation === 'delete'
1274+ ? 'Deleting'
1275+ : 'Writing'
12301276 const chunkTitle = args ?. title as string | undefined
12311277 const target = args ? asPayloadRecord ( args . target ) : undefined
12321278 const targetFileName = target ?. fileName as string | undefined
@@ -1237,6 +1283,25 @@ export function useChat(
12371283 }
12381284 }
12391285
1286+ if ( name === 'edit_content' ) {
1287+ const parentToolCallId =
1288+ activeFilePreviewToolCallIdRef . current ?? streamingFileRef . current ?. toolCallId
1289+ const parentIdx =
1290+ parentToolCallId !== null && parentToolCallId !== undefined
1291+ ? toolMap . get ( parentToolCallId )
1292+ : undefined
1293+ if ( parentIdx !== undefined && blocks [ parentIdx ] . toolCall ) {
1294+ toolMap . set ( id , parentIdx )
1295+ editContentParentToolCallIdRef . current . set ( id , parentToolCallId ! )
1296+ const tc = blocks [ parentIdx ] . toolCall !
1297+ tc . status = 'executing'
1298+ tc . result = undefined
1299+ tc . error = undefined
1300+ flush ( )
1301+ break
1302+ }
1303+ }
1304+
12401305 if ( ! toolMap . has ( id ) ) {
12411306 toolMap . set ( id , blocks . length )
12421307 blocks . push ( {
@@ -1608,6 +1673,7 @@ export function useChat(
16081673 } ,
16091674 [ fetchStreamBatch ]
16101675 )
1676+ attachToExistingStreamRef . current = attachToExistingStream
16111677
16121678 const resumeOrFinalize = useCallback (
16131679 async ( opts : {
@@ -2054,6 +2120,7 @@ export function useChat(
20542120 streamingFileRef . current = null
20552121 filePreviewSessionsRef . current . clear ( )
20562122 activeFilePreviewToolCallIdRef . current = null
2123+ editContentParentToolCallIdRef . current . clear ( )
20572124 setResources ( ( rs ) => rs . filter ( ( resource ) => resource . id !== 'streaming-file' ) )
20582125
20592126 const execState = useExecutionStore . getState ( )
0 commit comments