@@ -1190,16 +1190,22 @@ export function useChat(
11901190
11911191 if ( storedBlocks . length > 0 ) {
11921192 storedBlocks . push ( { type : 'stopped' } )
1193+ storedBlocks . push ( { type : 'text' , content : CONTINUE_OPTIONS_CONTENT } )
11931194 }
11941195
1196+ const persistedContent =
1197+ content && ! content . includes ( '<options>' )
1198+ ? content + '\n\n' + CONTINUE_OPTIONS_CONTENT
1199+ : content
1200+
11951201 try {
11961202 const res = await fetch ( stopPathRef . current , {
11971203 method : 'POST' ,
11981204 headers : { 'Content-Type' : 'application/json' } ,
11991205 body : JSON . stringify ( {
12001206 chatId,
12011207 streamId,
1202- content,
1208+ content : persistedContent ,
12031209 ...( storedBlocks . length > 0 && { contentBlocks : storedBlocks } ) ,
12041210 } ) ,
12051211 } )
@@ -1225,6 +1231,45 @@ export function useChat(
12251231 const messagesRef = useRef ( messages )
12261232 messagesRef . current = messages
12271233
1234+ const CONTINUE_OPTIONS_CONTENT =
1235+ '<options>{"continue":{"title":"Continue","description":"Pick up where we left off"}}</options>'
1236+
1237+ const resolveInterruptedToolCalls = useCallback ( ( ) => {
1238+ setMessages ( ( prev ) => {
1239+ let lastAssistantIdx = - 1
1240+ for ( let i = prev . length - 1 ; i >= 0 ; i -- ) {
1241+ if ( prev [ i ] . role === 'assistant' ) {
1242+ lastAssistantIdx = i
1243+ break
1244+ }
1245+ }
1246+ return prev . map ( ( msg , idx ) => {
1247+ const hasExecuting = msg . contentBlocks ?. some ( ( b ) => b . toolCall ?. status === 'executing' )
1248+ const isLastAssistant = idx === lastAssistantIdx
1249+ if ( ! hasExecuting && ! isLastAssistant ) return msg
1250+
1251+ const blocks : ContentBlock [ ] = ( msg . contentBlocks ?? [ ] ) . map ( ( block ) => {
1252+ if ( block . toolCall ?. status !== 'executing' ) return block
1253+ return {
1254+ ...block ,
1255+ toolCall : {
1256+ ...block . toolCall ,
1257+ status : 'cancelled' as const ,
1258+ displayTitle : 'Stopped' ,
1259+ } ,
1260+ }
1261+ } )
1262+ if ( isLastAssistant && ! blocks . some ( ( b ) => b . type === 'stopped' ) ) {
1263+ blocks . push ( { type : 'stopped' as const } )
1264+ }
1265+ if ( isLastAssistant && ! blocks . some ( ( b ) => b . type === 'text' && b . content ?. includes ( '<options>' ) ) ) {
1266+ blocks . push ( { type : 'text' , content : CONTINUE_OPTIONS_CONTENT } )
1267+ }
1268+ return { ...msg , contentBlocks : blocks . length > 0 ? blocks : msg . contentBlocks }
1269+ } )
1270+ } )
1271+ } , [ ] )
1272+
12281273 const finalize = useCallback (
12291274 ( options ?: { error ?: boolean } ) => {
12301275 sendingRef . current = false
@@ -1239,6 +1284,8 @@ export function useChat(
12391284 }
12401285 }
12411286
1287+ resolveInterruptedToolCalls ( )
1288+
12421289 if ( options ?. error ) {
12431290 setMessageQueue ( [ ] )
12441291 return
@@ -1254,7 +1301,7 @@ export function useChat(
12541301 } )
12551302 }
12561303 } ,
1257- [ invalidateChatQueries ]
1304+ [ invalidateChatQueries , resolveInterruptedToolCalls ]
12581305 )
12591306 finalizeRef . current = finalize
12601307
@@ -1412,24 +1459,7 @@ export function useChat(
14121459 sendingRef . current = false
14131460 setIsSending ( false )
14141461
1415- setMessages ( ( prev ) =>
1416- prev . map ( ( msg ) => {
1417- if ( ! msg . contentBlocks ?. some ( ( b ) => b . toolCall ?. status === 'executing' ) ) return msg
1418- const updated = msg . contentBlocks ! . map ( ( block ) => {
1419- if ( block . toolCall ?. status !== 'executing' ) return block
1420- return {
1421- ...block ,
1422- toolCall : {
1423- ...block . toolCall ,
1424- status : 'cancelled' as const ,
1425- displayTitle : 'Stopped by user' ,
1426- } ,
1427- }
1428- } )
1429- updated . push ( { type : 'stopped' as const } )
1430- return { ...msg , contentBlocks : updated }
1431- } )
1432- )
1462+ resolveInterruptedToolCalls ( )
14331463
14341464 if ( sid ) {
14351465 fetch ( '/api/copilot/chat/abort' , {
@@ -1495,7 +1525,7 @@ export function useChat(
14951525
14961526 reportManualRunToolStop ( workflowId , toolCallId ) . catch ( ( ) => { } )
14971527 }
1498- } , [ invalidateChatQueries , persistPartialResponse , executionStream ] )
1528+ } , [ invalidateChatQueries , persistPartialResponse , executionStream , resolveInterruptedToolCalls ] )
14991529
15001530 const removeFromQueue = useCallback ( ( id : string ) => {
15011531 messageQueueRef . current = messageQueueRef . current . filter ( ( m ) => m . id !== id )
0 commit comments