({
inputRef,
activeSubagentsRef,
isChainInProgressRef,
setStreamStatus,
setCanProcessQueue,
abortControllerRef,
agentId,
onBeforeMessageSend,
mainAgentTimer,
scrollToLatest,
onTimerEvent = () => {},
isQueuePausedRef,
isProcessingQueueRef,
resumeQueue,
continueChat,
continueChatId,
subscriptionData,
}: UseSendMessageOptions)
| 99 | } |
| 100 | |
| 101 | export const useSendMessage = ({ |
| 102 | inputRef, |
| 103 | activeSubagentsRef, |
| 104 | isChainInProgressRef, |
| 105 | setStreamStatus, |
| 106 | setCanProcessQueue, |
| 107 | abortControllerRef, |
| 108 | agentId, |
| 109 | onBeforeMessageSend, |
| 110 | mainAgentTimer, |
| 111 | scrollToLatest, |
| 112 | onTimerEvent = () => {}, |
| 113 | isQueuePausedRef, |
| 114 | isProcessingQueueRef, |
| 115 | resumeQueue, |
| 116 | continueChat, |
| 117 | continueChatId, |
| 118 | subscriptionData, |
| 119 | }: UseSendMessageOptions): { |
| 120 | sendMessage: SendMessageFn |
| 121 | clearMessages: () => void |
| 122 | } => { |
| 123 | // Pull setters directly from store - these are stable references that don't need |
| 124 | // to trigger re-renders, so using getState() outside of callbacks is intentional. |
| 125 | const { |
| 126 | setMessages, |
| 127 | setFocusedAgentId, |
| 128 | setInputFocused, |
| 129 | setStreamingAgents, |
| 130 | setActiveSubagents, |
| 131 | setIsChainInProgress, |
| 132 | setHasReceivedPlanResponse, |
| 133 | setLastMessageMode, |
| 134 | addSessionCredits, |
| 135 | setRunState, |
| 136 | setIsRetrying, |
| 137 | } = useChatStore.getState() |
| 138 | const previousRunStateRef = useRef<RunState | null>( |
| 139 | useChatStore.getState().runState, |
| 140 | ) |
| 141 | // Memoize stream controller to maintain referential stability across renders |
| 142 | const streamRefsRef = useRef<ReturnType< |
| 143 | typeof createStreamController |
| 144 | > | null>(null) |
| 145 | if (!streamRefsRef.current) { |
| 146 | streamRefsRef.current = createStreamController() |
| 147 | } |
| 148 | const streamRefs = streamRefsRef.current |
| 149 | |
| 150 | useEffect(() => { |
| 151 | if (continueChat && !previousRunStateRef.current) { |
| 152 | const loadedState = loadMostRecentChatState(continueChatId ?? undefined) |
| 153 | if (loadedState) { |
| 154 | previousRunStateRef.current = loadedState.runState |
| 155 | setRunState(loadedState.runState) |
| 156 | setMessages(loadedState.messages) |
| 157 | if (loadedState.chatId) { |
| 158 | setCurrentChatId(loadedState.chatId) |
no test coverage detected