fix: lagging issue in ask AI during message streaming (#16201)
## Changes ### 1. Fixed streaming lag with throttle parameter **Problem:** The AI chat was experiencing lag during message streaming because the messages array was being updated too frequently, causing all messages to re-render too quickly. **Solution:** Added the `experimental_throttle: 100` parameter to the `useChat` hook configuration. This throttles message updates during streaming to prevent excessive re-renders and improve performance. ### 2. Cleaned up useAgentChat hook return values **Context:** The `useAgentChat` hook primarily returns values from the underlying `useChat` hook, so there wasn't significant room for improvement regarding the "umbrella hook" pattern. However, some unnecessary values were being returned that weren't needed. **Solution:** - Removed `input` and `handleInputChange` from the `useAgentChat` hook return. These weren't needed since input state is already managed directly via Recoil state (`agentChatInputState`) in components. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Throttle message streaming updates and switch AI chat input management from context to Recoil; minor scroll behavior tweak. > > - **AI Chat performance**: > - Add `experimental_throttle: 100` to `useChat` in `useAgentChat` to reduce re-render frequency during streaming. > - **State management**: > - Migrate input handling to Recoil via `agentChatInputState`; remove `input` and `handleInputChange` from `AgentChatContext` and `useAgentChat` returns. > - Update `AIChatTab` and `SendMessageButton` to read/write input from Recoil and adjust hotkeys/disabled state accordingly. > - **UX behavior**: > - Remove smooth scroll behavior in `useAgentChatScrollToBottom`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 911b341ea1f7c63a4e1e27667da119d9a2960b78. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
@@ -19,10 +19,12 @@ import { AI_CHAT_INPUT_ID } from '@/ai/constants/AiChatInputId';
|
||||
import { AI_CHAT_SCROLL_WRAPPER_ID } from '@/ai/constants/AiChatScrollWrapperId';
|
||||
import { useAIChatFileUpload } from '@/ai/hooks/useAIChatFileUpload';
|
||||
import { useAgentChatContextOrThrow } from '@/ai/hooks/useAgentChatContextOrThrow';
|
||||
import { agentChatInputState } from '@/ai/states/agentChatInputState';
|
||||
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useState } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { Button } from 'twenty-ui/input';
|
||||
|
||||
const StyledContainer = styled.div<{ isDraggingFile: boolean }>`
|
||||
@@ -63,9 +65,12 @@ const StyledButtonsContainer = styled.div`
|
||||
export const AIChatTab = () => {
|
||||
const [isDraggingFile, setIsDraggingFile] = useState(false);
|
||||
|
||||
const { isLoading, input, handleInputChange, messages, isStreaming, error } =
|
||||
const { isLoading, messages, isStreaming, error } =
|
||||
useAgentChatContextOrThrow();
|
||||
|
||||
const [agentChatInput, setAgentChatInput] =
|
||||
useRecoilState(agentChatInputState);
|
||||
|
||||
const contextStoreCurrentObjectMetadataItemId = useRecoilComponentValue(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
);
|
||||
@@ -115,8 +120,8 @@ export const AIChatTab = () => {
|
||||
<TextArea
|
||||
textAreaId={AI_CHAT_INPUT_ID}
|
||||
placeholder={t`Enter a question...`}
|
||||
value={input}
|
||||
onChange={handleInputChange}
|
||||
value={agentChatInput}
|
||||
onChange={(value) => setAgentChatInput(value)}
|
||||
minRows={1}
|
||||
maxRows={20}
|
||||
/>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { AI_CHAT_INPUT_ID } from '@/ai/constants/AiChatInputId';
|
||||
import { useAgentChatContextOrThrow } from '@/ai/hooks/useAgentChatContextOrThrow';
|
||||
import { agentChatInputState } from '@/ai/states/agentChatInputState';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { Button } from 'twenty-ui/input';
|
||||
|
||||
@@ -11,7 +13,8 @@ export const SendMessageButton = ({
|
||||
}: {
|
||||
records?: ObjectRecord[];
|
||||
}) => {
|
||||
const { handleSendMessage, isLoading, input } = useAgentChatContextOrThrow();
|
||||
const agentChatInput = useRecoilValue(agentChatInputState);
|
||||
const { handleSendMessage, isLoading } = useAgentChatContextOrThrow();
|
||||
|
||||
useHotkeysOnFocusedElement({
|
||||
keys: [Key.Enter],
|
||||
@@ -22,7 +25,7 @@ export const SendMessageButton = ({
|
||||
}
|
||||
},
|
||||
focusId: AI_CHAT_INPUT_ID,
|
||||
dependencies: [input, isLoading],
|
||||
dependencies: [agentChatInput, isLoading],
|
||||
options: {
|
||||
enableOnFormTags: true,
|
||||
},
|
||||
@@ -30,9 +33,9 @@ export const SendMessageButton = ({
|
||||
|
||||
return (
|
||||
<Button
|
||||
hotkeys={input && !isLoading ? ['⏎'] : undefined}
|
||||
hotkeys={agentChatInput && !isLoading ? ['⏎'] : undefined}
|
||||
onClick={() => handleSendMessage(records)}
|
||||
disabled={!input || isLoading}
|
||||
disabled={!agentChatInput || isLoading}
|
||||
variant="primary"
|
||||
accent="blue"
|
||||
size="small"
|
||||
|
||||
@@ -8,9 +8,6 @@ export type AgentChatContextValue = {
|
||||
isLoading: boolean;
|
||||
error?: Error;
|
||||
|
||||
input: string;
|
||||
handleInputChange: (value: string) => void;
|
||||
|
||||
handleSendMessage: (records?: ObjectRecord[]) => Promise<void>;
|
||||
|
||||
handleRetry: () => void;
|
||||
|
||||
@@ -110,6 +110,7 @@ export const useAgentChat = (uiMessages: ExtendedUIMessage[]) => {
|
||||
}),
|
||||
messages: uiMessages,
|
||||
id: `${currentAIChatThread}-${uiMessages.length}`,
|
||||
experimental_throttle: 100,
|
||||
});
|
||||
|
||||
const isStreaming = status === 'streaming';
|
||||
@@ -156,9 +157,7 @@ export const useAgentChat = (uiMessages: ExtendedUIMessage[]) => {
|
||||
};
|
||||
|
||||
return {
|
||||
handleInputChange: (value: string) => setAgentChatInput(value),
|
||||
messages,
|
||||
input: agentChatInput,
|
||||
handleSendMessage,
|
||||
isLoading,
|
||||
isStreaming,
|
||||
|
||||
@@ -15,7 +15,6 @@ export const useAgentChatScrollToBottom = () => {
|
||||
|
||||
scrollWrapperElement.scrollTo({
|
||||
top: scrollWrapperElement.scrollHeight,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user