fix(ask-ai): resolve stream subscription race condition on new thread… (#21916)
## Description Resolves a race condition in the Ask AI feature where the first assistant reply in a newly created thread does not stream into the UI and only appears after sending a second message. ### What's Changed - **Immediate Thread Subscription:** Updated `useAgentChat.ts` to immediately set `currentAiChatThread` to the newly generated `threadId` instead of deferring it until after the `SEND_CHAT_MESSAGE` mutation finishes. - **The Bug:** Previously, the backend worker processed the AI chat job so quickly that the stream completed and fired the `message-persisted` event *before* the frontend established the SSE subscription. - **The Fix:** By setting the thread ID immediately, the `useAgentChatSubscription` hook now properly connects and listens to the SSE stream before the backend begins emitting chunks, guaranteeing the first message streams seamlessly. ### How to Test 1. Open the Ask AI panel and start a completely new thread. 2. Send an initial message (e.g., "Hello!"). 3. Observe that the AI's response successfully streams into the chat without needing a workaround or page refresh. Closes #21694 --------- Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { CombinedGraphQLErrors } from '@apollo/client/errors';
|
||||
import { useApolloClient } from '@apollo/client/react';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { type ExtendedUIMessage } from 'twenty-shared/ai';
|
||||
import { isDefined, isValidUuid } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
@@ -44,8 +44,6 @@ export const useAgentChat = (
|
||||
const setCurrentAiChatThread = useSetAtomState(currentAiChatThreadState);
|
||||
const store = useStore();
|
||||
|
||||
const [, setPendingThreadIdAfterFirstSend] = useState<string | null>(null);
|
||||
|
||||
const setAgentChatUploadedFiles = useSetAtomState(
|
||||
agentChatUploadedFilesState,
|
||||
);
|
||||
@@ -87,7 +85,7 @@ export const useAgentChat = (
|
||||
}
|
||||
|
||||
if (draftKey === AGENT_CHAT_NEW_THREAD_DRAFT_KEY) {
|
||||
setPendingThreadIdAfterFirstSend(threadId);
|
||||
setCurrentAiChatThread(threadId);
|
||||
}
|
||||
|
||||
setAgentChatInput('');
|
||||
@@ -184,14 +182,6 @@ export const useAgentChat = (
|
||||
}
|
||||
|
||||
dispatchBrowserEvent(AGENT_CHAT_REFETCH_MESSAGES_EVENT_NAME);
|
||||
|
||||
setPendingThreadIdAfterFirstSend((pendingId) => {
|
||||
if (isDefined(pendingId)) {
|
||||
setCurrentAiChatThread(pendingId);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
} catch (error) {
|
||||
const restoredDraftKey =
|
||||
draftKey === AGENT_CHAT_NEW_THREAD_DRAFT_KEY ? threadId : draftKey;
|
||||
@@ -225,12 +215,6 @@ export const useAgentChat = (
|
||||
dispatchBrowserEvent(AGENT_CHAT_RESTORE_EDITOR_CONTENT_EVENT_NAME, {
|
||||
content: contentToSend,
|
||||
});
|
||||
|
||||
if (draftKey === AGENT_CHAT_NEW_THREAD_DRAFT_KEY) {
|
||||
setCurrentAiChatThread(threadId);
|
||||
}
|
||||
|
||||
setPendingThreadIdAfterFirstSend(null);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
|
||||
Reference in New Issue
Block a user