import type { MutableRefObject } from "react"; import { chatEventBus } from "../event-buses"; import type { ChatMessage, ChatMessageText } from "../types"; import type { StreamingMessageManager } from "./streaming"; import { createBotMessage } from "./streaming"; type AppendMessageFn = (message: ChatMessage) => void; type ReplaceMessageFn = (messageId: string, message: ChatMessageText) => void; function scheduleScrollToBottom() { if (typeof queueMicrotask === "function") { queueMicrotask(() => { chatEventBus.emit("scrollToBottom"); }); return; } setTimeout(() => { chatEventBus.emit("scrollToBottom"); }, 0); } export function handleStreamingChunk( chunk: string, nodeId: string | undefined, streamingManager: StreamingMessageManager, receivedMessage: MutableRefObject, appendMessage: AppendMessageFn, replaceMessage: ReplaceMessageFn, runIndex?: number, ): void { try { if (chunk === "") return; if (!nodeId) { if (!receivedMessage.current) { receivedMessage.current = createBotMessage(); appendMessage(receivedMessage.current); } const updatedMessage: ChatMessageText = { ...receivedMessage.current, text: (receivedMessage.current?.text ?? "") + chunk, }; replaceMessage(updatedMessage.id, updatedMessage); receivedMessage.current = updatedMessage; } else { if (!streamingManager) { scheduleScrollToBottom(); return; } let runMessage = streamingManager.getRunMessage(nodeId, runIndex); if (!runMessage) { runMessage = streamingManager.addRunToActive(nodeId, runIndex); appendMessage(runMessage); } const updatedMessage = streamingManager.addChunkToRun( nodeId, chunk, runIndex, ); if (updatedMessage) { replaceMessage(updatedMessage.id, updatedMessage); } } scheduleScrollToBottom(); } catch (error) { console.error("Error handling stream chunk:", error); } } export function handleNodeStart( nodeId: string, streamingManager: StreamingMessageManager, runIndex?: number, ): void { try { if (!streamingManager) return; streamingManager.registerRunStart(nodeId, runIndex); } catch (error) { console.error("Error handling node start:", error); } } export function handleNodeComplete( nodeId: string, streamingManager: StreamingMessageManager, runIndex?: number, ): ChatMessageText | null { try { if (!streamingManager) return null; streamingManager.removeRunFromActive(nodeId, runIndex); return streamingManager.getRunMessage(nodeId, runIndex); } catch (error) { console.error("Error handling node complete:", error); } return null; }