diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/message-content/message-content.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/message-content/message-content.tsx index e91a710b590..757d57e9da3 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/message-content/message-content.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/message-content/message-content.tsx @@ -413,7 +413,9 @@ export function MessageContent({ return (
- Stopped + + Stopped by user +
) } diff --git a/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts b/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts index 90e76f6be6f..b2667577992 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts +++ b/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts @@ -85,8 +85,6 @@ const STATE_TO_STATUS: Record = { const DEPLOY_TOOL_NAMES = new Set(['deploy_api', 'deploy_chat', 'deploy_mcp', 'redeploy']) const RECONNECT_TAIL_ERROR = 'Live reconnect failed before the stream finished. The latest response may be incomplete.' -const CONTINUE_OPTIONS_CONTENT = - '{"continue":{"title":"Continue","description":"Pick up where we left off"}}' function mapStoredBlock(block: TaskStoredContentBlock): ContentBlock { const mapped: ContentBlock = { @@ -1215,14 +1213,8 @@ export function useChat( if (storedBlocks.length > 0) { storedBlocks.push({ type: 'stopped' }) - storedBlocks.push({ type: 'text', content: CONTINUE_OPTIONS_CONTENT }) } - const persistedContent = - content && !content.includes('') - ? `${content}\n\n${CONTINUE_OPTIONS_CONTENT}` - : content - try { const res = await fetch(stopPathRef.current, { method: 'POST', @@ -1230,7 +1222,7 @@ export function useChat( body: JSON.stringify({ chatId, streamId, - content: persistedContent, + content, ...(storedBlocks.length > 0 && { contentBlocks: storedBlocks }), }), }) @@ -1256,50 +1248,6 @@ export function useChat( const messagesRef = useRef(messages) messagesRef.current = messages - const resolveInterruptedToolCalls = useCallback(() => { - setMessages((prev) => { - const hasAnyExecuting = prev.some((m) => - m.contentBlocks?.some((b) => b.toolCall?.status === 'executing') - ) - if (!hasAnyExecuting) return prev - - let lastAssistantIdx = -1 - for (let i = prev.length - 1; i >= 0; i--) { - if (prev[i].role === 'assistant') { - lastAssistantIdx = i - break - } - } - return prev.map((msg, idx) => { - const hasExecuting = msg.contentBlocks?.some((b) => b.toolCall?.status === 'executing') - const isLastAssistant = idx === lastAssistantIdx - if (!hasExecuting && !isLastAssistant) return msg - - const blocks: ContentBlock[] = (msg.contentBlocks ?? []).map((block) => { - if (block.toolCall?.status !== 'executing') return block - return { - ...block, - toolCall: { - ...block.toolCall, - status: 'cancelled' as const, - displayTitle: 'Stopped', - }, - } - }) - if (isLastAssistant && !blocks.some((b) => b.type === 'stopped')) { - blocks.push({ type: 'stopped' as const }) - } - if ( - isLastAssistant && - !blocks.some((b) => b.type === 'text' && b.content?.includes('')) - ) { - blocks.push({ type: 'text', content: CONTINUE_OPTIONS_CONTENT }) - } - return { ...msg, contentBlocks: blocks.length > 0 ? blocks : msg.contentBlocks } - }) - }) - }, []) - const finalize = useCallback( (options?: { error?: boolean }) => { sendingRef.current = false @@ -1314,8 +1262,6 @@ export function useChat( } } - resolveInterruptedToolCalls() - if (options?.error) { setMessageQueue([]) return @@ -1331,7 +1277,7 @@ export function useChat( }) } }, - [invalidateChatQueries, resolveInterruptedToolCalls] + [invalidateChatQueries] ) finalizeRef.current = finalize @@ -1489,7 +1435,24 @@ export function useChat( sendingRef.current = false setIsSending(false) - resolveInterruptedToolCalls() + setMessages((prev) => + prev.map((msg) => { + if (!msg.contentBlocks?.some((b) => b.toolCall?.status === 'executing')) return msg + const updated = msg.contentBlocks!.map((block) => { + if (block.toolCall?.status !== 'executing') return block + return { + ...block, + toolCall: { + ...block.toolCall, + status: 'cancelled' as const, + displayTitle: 'Stopped by user', + }, + } + }) + updated.push({ type: 'stopped' as const }) + return { ...msg, contentBlocks: updated } + }) + ) if (sid) { fetch('/api/copilot/chat/abort', { @@ -1555,7 +1518,7 @@ export function useChat( reportManualRunToolStop(workflowId, toolCallId).catch(() => {}) } - }, [invalidateChatQueries, persistPartialResponse, executionStream, resolveInterruptedToolCalls]) + }, [invalidateChatQueries, persistPartialResponse, executionStream]) const removeFromQueue = useCallback((id: string) => { messageQueueRef.current = messageQueueRef.current.filter((m) => m.id !== id) diff --git a/bun.lock b/bun.lock index 742b7d9079e..ed31b1d954d 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "simstudio",