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 6c1031c343..8b5703ffbb 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts +++ b/apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts @@ -368,6 +368,15 @@ export function useChat( options?: { preserveExistingState?: boolean } ) => Promise<{ sawStreamError: boolean; sawComplete: boolean }> >(async () => ({ sawStreamError: false, sawComplete: false })) + const attachToExistingStreamRef = useRef< + (opts: { + streamId: string + assistantId: string + expectedGen: number + initialBatch?: StreamBatchResponse | null + afterCursor?: string + }) => Promise<{ error: boolean; aborted: boolean }> + >(async () => ({ error: false, aborted: true })) const retryReconnectRef = useRef< (opts: { streamId: string; assistantId: string; gen: number }) => Promise >(async () => false) @@ -617,7 +626,7 @@ export function useChat( const reconnectResult = snapshotEvents.length > 0 - ? await attachToExistingStream({ + ? await attachToExistingStreamRef.current({ streamId: activeStreamId, assistantId, expectedGen: gen, @@ -1613,6 +1622,7 @@ export function useChat( }, [fetchStreamBatch] ) + attachToExistingStreamRef.current = attachToExistingStream const resumeOrFinalize = useCallback( async (opts: { diff --git a/apps/sim/lib/copilot/request/lifecycle/run.ts b/apps/sim/lib/copilot/request/lifecycle/run.ts index f5d15cf767..c96fe42afa 100644 --- a/apps/sim/lib/copilot/request/lifecycle/run.ts +++ b/apps/sim/lib/copilot/request/lifecycle/run.ts @@ -282,6 +282,12 @@ async function runCheckpointLoop( ) } + if (isAborted(options, context)) { + cancelPendingTools(context) + context.awaitingAsyncContinuation = undefined + break + } + const results: Array<{ callId: string name: string @@ -289,6 +295,11 @@ async function runCheckpointLoop( success: boolean }> = [] for (const toolCallId of continuation.pendingToolCallIds) { + if (isAborted(options, context)) { + cancelPendingTools(context) + context.awaitingAsyncContinuation = undefined + break + } const tool = context.toolCalls.get(toolCallId) if (!tool || (!tool.result && !tool.error)) { logger.error('Missing tool result for pending tool call', { @@ -309,6 +320,12 @@ async function runCheckpointLoop( }) } + if (isAborted(options, context)) { + cancelPendingTools(context) + context.awaitingAsyncContinuation = undefined + break + } + logger.info('Resuming with tool results', { checkpointId: continuation.checkpointId, runId: continuation.runId, @@ -324,6 +341,13 @@ async function runCheckpointLoop( checkpointId: continuation.checkpointId, results, } + + if (isAborted(options, context)) { + cancelPendingTools(context) + context.awaitingAsyncContinuation = undefined + break + } + logger.info('Prepared resume request payload', { route, streamId: context.messageId,