mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-10-10 05:05:34 +02:00
Fix misc chat bugs
This commit is contained in:
@@ -12,7 +12,6 @@ import {
|
|||||||
Message,
|
Message,
|
||||||
RetrievalType,
|
RetrievalType,
|
||||||
StreamingError,
|
StreamingError,
|
||||||
ToolCallFinalResult,
|
|
||||||
ToolCallMetadata,
|
ToolCallMetadata,
|
||||||
} from "./interfaces";
|
} from "./interfaces";
|
||||||
import { ChatSidebar } from "./sessionSidebar/ChatSidebar";
|
import { ChatSidebar } from "./sessionSidebar/ChatSidebar";
|
||||||
@@ -35,7 +34,6 @@ import {
|
|||||||
removeMessage,
|
removeMessage,
|
||||||
sendMessage,
|
sendMessage,
|
||||||
setMessageAsLatest,
|
setMessageAsLatest,
|
||||||
updateModelOverrideForChatSession,
|
|
||||||
updateParentChildren,
|
updateParentChildren,
|
||||||
uploadFilesForChat,
|
uploadFilesForChat,
|
||||||
useScrollonStream,
|
useScrollonStream,
|
||||||
@@ -61,11 +59,7 @@ import { AnswerPiecePacket, DanswerDocument } from "@/lib/search/interfaces";
|
|||||||
import { buildFilters } from "@/lib/search/utils";
|
import { buildFilters } from "@/lib/search/utils";
|
||||||
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
||||||
import Dropzone from "react-dropzone";
|
import Dropzone from "react-dropzone";
|
||||||
import {
|
import { checkLLMSupportsImageInput, getFinalLLM } from "@/lib/llm/utils";
|
||||||
checkLLMSupportsImageInput,
|
|
||||||
getFinalLLM,
|
|
||||||
structureValue,
|
|
||||||
} from "@/lib/llm/utils";
|
|
||||||
import { ChatInputBar } from "./input/ChatInputBar";
|
import { ChatInputBar } from "./input/ChatInputBar";
|
||||||
import { ConfigurationModal } from "./modal/configuration/ConfigurationModal";
|
import { ConfigurationModal } from "./modal/configuration/ConfigurationModal";
|
||||||
import { useChatContext } from "@/components/context/ChatContext";
|
import { useChatContext } from "@/components/context/ChatContext";
|
||||||
@@ -118,10 +112,10 @@ export function ChatPage({
|
|||||||
const existingChatSessionId = existingChatIdRaw
|
const existingChatSessionId = existingChatIdRaw
|
||||||
? parseInt(existingChatIdRaw)
|
? parseInt(existingChatIdRaw)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const selectedChatSession = chatSessions.find(
|
const selectedChatSession = chatSessions.find(
|
||||||
(chatSession) => chatSession.id === existingChatSessionId
|
(chatSession) => chatSession.id === existingChatSessionId
|
||||||
);
|
);
|
||||||
|
const chatSessionIdRef = useRef<number | null>(existingChatSessionId);
|
||||||
|
|
||||||
const llmOverrideManager = useLlmOverride(selectedChatSession);
|
const llmOverrideManager = useLlmOverride(selectedChatSession);
|
||||||
|
|
||||||
@@ -140,35 +134,22 @@ export function ChatPage({
|
|||||||
existingChatSessionId !== null
|
existingChatSessionId !== null
|
||||||
);
|
);
|
||||||
|
|
||||||
// needed so closures (e.g. onSubmit) can access the current value
|
|
||||||
const urlChatSessionId = useRef<number | null>();
|
|
||||||
// this is triggered every time the user switches which chat
|
// this is triggered every time the user switches which chat
|
||||||
// session they are using
|
// session they are using
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
const priorChatSessionId = chatSessionIdRef.current;
|
||||||
chatSessionId &&
|
chatSessionIdRef.current = existingChatSessionId;
|
||||||
!urlChatSessionId.current &&
|
|
||||||
llmOverrideManager.llmOverride
|
|
||||||
) {
|
|
||||||
updateModelOverrideForChatSession(
|
|
||||||
chatSessionId,
|
|
||||||
structureValue(
|
|
||||||
llmOverrideManager.llmOverride.name,
|
|
||||||
llmOverrideManager.llmOverride.provider,
|
|
||||||
llmOverrideManager.llmOverride.modelName
|
|
||||||
) as string
|
|
||||||
);
|
|
||||||
}
|
|
||||||
urlChatSessionId.current = existingChatSessionId;
|
|
||||||
textAreaRef.current?.focus();
|
textAreaRef.current?.focus();
|
||||||
|
|
||||||
// only clear things if we're going from one chat session to another
|
// only clear things if we're going from one chat session to another
|
||||||
|
const isChatSessionSwitch =
|
||||||
if (chatSessionId !== null && existingChatSessionId !== chatSessionId) {
|
chatSessionIdRef.current !== null &&
|
||||||
|
existingChatSessionId !== priorChatSessionId;
|
||||||
|
if (isChatSessionSwitch) {
|
||||||
// de-select documents
|
// de-select documents
|
||||||
clearSelectedDocuments();
|
clearSelectedDocuments();
|
||||||
// reset all filters
|
|
||||||
|
|
||||||
|
// reset all filters
|
||||||
filterManager.setSelectedDocumentSets([]);
|
filterManager.setSelectedDocumentSets([]);
|
||||||
filterManager.setSelectedSources([]);
|
filterManager.setSelectedSources([]);
|
||||||
filterManager.setSelectedTags([]);
|
filterManager.setSelectedTags([]);
|
||||||
@@ -177,16 +158,21 @@ export function ChatPage({
|
|||||||
// reset LLM overrides (based on chat session!)
|
// reset LLM overrides (based on chat session!)
|
||||||
llmOverrideManager.updateModelOverrideForChatSession(selectedChatSession);
|
llmOverrideManager.updateModelOverrideForChatSession(selectedChatSession);
|
||||||
llmOverrideManager.setTemperature(null);
|
llmOverrideManager.setTemperature(null);
|
||||||
|
|
||||||
// remove uploaded files
|
// remove uploaded files
|
||||||
setCurrentMessageFiles([]);
|
setCurrentMessageFiles([]);
|
||||||
|
|
||||||
|
// if switching from one chat to another, then need to scroll again
|
||||||
|
// if we're creating a brand new chat, then don't need to scroll
|
||||||
|
if (chatSessionIdRef.current !== null) {
|
||||||
|
setHasPerformedInitialScroll(false);
|
||||||
|
}
|
||||||
|
|
||||||
if (isStreaming) {
|
if (isStreaming) {
|
||||||
setIsCancelled(true);
|
setIsCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setChatSessionId(existingChatSessionId);
|
|
||||||
|
|
||||||
async function initialSessionFetch() {
|
async function initialSessionFetch() {
|
||||||
if (existingChatSessionId === null) {
|
if (existingChatSessionId === null) {
|
||||||
setIsFetchingChatMessages(false);
|
setIsFetchingChatMessages(false);
|
||||||
@@ -199,7 +185,10 @@ export function ChatPage({
|
|||||||
} else {
|
} else {
|
||||||
setSelectedPersona(undefined);
|
setSelectedPersona(undefined);
|
||||||
}
|
}
|
||||||
setCompleteMessageMap(new Map());
|
setCompleteMessageDetail({
|
||||||
|
sessionId: null,
|
||||||
|
messageMap: new Map(),
|
||||||
|
});
|
||||||
setChatSessionSharedStatus(ChatSessionSharedStatus.Private);
|
setChatSessionSharedStatus(ChatSessionSharedStatus.Private);
|
||||||
|
|
||||||
// if we're supposed to submit on initial load, then do that here
|
// if we're supposed to submit on initial load, then do that here
|
||||||
@@ -226,11 +215,14 @@ export function ChatPage({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const newCompleteMessageMap = processRawChatHistory(chatSession.messages);
|
const newMessageMap = processRawChatHistory(chatSession.messages);
|
||||||
const newMessageHistory = buildLatestMessageChain(newCompleteMessageMap);
|
const newMessageHistory = buildLatestMessageChain(newMessageMap);
|
||||||
// if the last message is an error, don't overwrite it
|
// if the last message is an error, don't overwrite it
|
||||||
if (messageHistory[messageHistory.length - 1]?.type !== "error") {
|
if (messageHistory[messageHistory.length - 1]?.type !== "error") {
|
||||||
setCompleteMessageMap(newCompleteMessageMap);
|
setCompleteMessageDetail({
|
||||||
|
sessionId: chatSession.chat_session_id,
|
||||||
|
messageMap: newMessageMap,
|
||||||
|
});
|
||||||
|
|
||||||
const latestMessageId =
|
const latestMessageId =
|
||||||
newMessageHistory[newMessageHistory.length - 1]?.messageId;
|
newMessageHistory[newMessageHistory.length - 1]?.messageId;
|
||||||
@@ -241,6 +233,13 @@ export function ChatPage({
|
|||||||
|
|
||||||
setChatSessionSharedStatus(chatSession.shared_status);
|
setChatSessionSharedStatus(chatSession.shared_status);
|
||||||
|
|
||||||
|
// go to bottom. If initial load, then do a scroll,
|
||||||
|
// otherwise just appear at the bottom
|
||||||
|
if (!hasPerformedInitialScroll) {
|
||||||
|
clientScrollToBottom();
|
||||||
|
} else if (isChatSessionSwitch) {
|
||||||
|
clientScrollToBottom(true);
|
||||||
|
}
|
||||||
setIsFetchingChatMessages(false);
|
setIsFetchingChatMessages(false);
|
||||||
|
|
||||||
// if this is a seeded chat, then kick off the AI message generation
|
// if this is a seeded chat, then kick off the AI message generation
|
||||||
@@ -279,18 +278,17 @@ export function ChatPage({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const [chatSessionId, setChatSessionId] = useState<number | null>(
|
|
||||||
existingChatSessionId
|
|
||||||
);
|
|
||||||
const [message, setMessage] = useState(
|
const [message, setMessage] = useState(
|
||||||
searchParams.get(SEARCH_PARAM_NAMES.USER_MESSAGE) || ""
|
searchParams.get(SEARCH_PARAM_NAMES.USER_MESSAGE) || ""
|
||||||
);
|
);
|
||||||
const [completeMessageMap, setCompleteMessageMap] = useState<
|
const [completeMessageDetail, setCompleteMessageDetail] = useState<{
|
||||||
Map<number, Message>
|
sessionId: number | null;
|
||||||
>(new Map());
|
messageMap: Map<number, Message>;
|
||||||
|
}>({ sessionId: null, messageMap: new Map() });
|
||||||
const upsertToCompleteMessageMap = ({
|
const upsertToCompleteMessageMap = ({
|
||||||
messages,
|
messages,
|
||||||
completeMessageMapOverride,
|
completeMessageMapOverride,
|
||||||
|
chatSessionId,
|
||||||
replacementsMap = null,
|
replacementsMap = null,
|
||||||
makeLatestChildMessage = false,
|
makeLatestChildMessage = false,
|
||||||
}: {
|
}: {
|
||||||
@@ -298,12 +296,13 @@ export function ChatPage({
|
|||||||
// if calling this function repeatedly with short delay, stay may not update in time
|
// if calling this function repeatedly with short delay, stay may not update in time
|
||||||
// and result in weird behavipr
|
// and result in weird behavipr
|
||||||
completeMessageMapOverride?: Map<number, Message> | null;
|
completeMessageMapOverride?: Map<number, Message> | null;
|
||||||
|
chatSessionId?: number;
|
||||||
replacementsMap?: Map<number, number> | null;
|
replacementsMap?: Map<number, number> | null;
|
||||||
makeLatestChildMessage?: boolean;
|
makeLatestChildMessage?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
// deep copy
|
// deep copy
|
||||||
const frozenCompleteMessageMap =
|
const frozenCompleteMessageMap =
|
||||||
completeMessageMapOverride || completeMessageMap;
|
completeMessageMapOverride || completeMessageDetail.messageMap;
|
||||||
const newCompleteMessageMap = structuredClone(frozenCompleteMessageMap);
|
const newCompleteMessageMap = structuredClone(frozenCompleteMessageMap);
|
||||||
if (newCompleteMessageMap.size === 0) {
|
if (newCompleteMessageMap.size === 0) {
|
||||||
const systemMessageId = messages[0].parentMessageId || SYSTEM_MESSAGE_ID;
|
const systemMessageId = messages[0].parentMessageId || SYSTEM_MESSAGE_ID;
|
||||||
@@ -352,11 +351,17 @@ export function ChatPage({
|
|||||||
)!.latestChildMessageId = messages[0].messageId;
|
)!.latestChildMessageId = messages[0].messageId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setCompleteMessageMap(newCompleteMessageMap);
|
const newCompleteMessageDetail = {
|
||||||
return newCompleteMessageMap;
|
sessionId: chatSessionId || completeMessageDetail.sessionId,
|
||||||
|
messageMap: newCompleteMessageMap,
|
||||||
|
};
|
||||||
|
setCompleteMessageDetail(newCompleteMessageDetail);
|
||||||
|
return newCompleteMessageDetail;
|
||||||
};
|
};
|
||||||
|
|
||||||
const messageHistory = buildLatestMessageChain(completeMessageMap);
|
const messageHistory = buildLatestMessageChain(
|
||||||
|
completeMessageDetail.messageMap
|
||||||
|
);
|
||||||
const [isStreaming, setIsStreaming] = useState(false);
|
const [isStreaming, setIsStreaming] = useState(false);
|
||||||
|
|
||||||
// uploaded files
|
// uploaded files
|
||||||
@@ -393,7 +398,7 @@ export function ChatPage({
|
|||||||
useState<ChatSessionSharedStatus>(ChatSessionSharedStatus.Private);
|
useState<ChatSessionSharedStatus>(ChatSessionSharedStatus.Private);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (messageHistory.length === 0 && chatSessionId === null) {
|
if (messageHistory.length === 0 && chatSessionIdRef.current === null) {
|
||||||
setSelectedPersona(
|
setSelectedPersona(
|
||||||
filteredAssistants.find(
|
filteredAssistants.find(
|
||||||
(persona) => persona.id === defaultSelectedPersonaId
|
(persona) => persona.id === defaultSelectedPersonaId
|
||||||
@@ -481,7 +486,10 @@ export function ChatPage({
|
|||||||
scrollableDivRef.current
|
scrollableDivRef.current
|
||||||
) {
|
) {
|
||||||
endPaddingRef.current.style.transition = "height 0.3s ease-out";
|
endPaddingRef.current.style.transition = "height 0.3s ease-out";
|
||||||
endPaddingRef.current.style.height = `${Math.max(newHeight - 50, 0)}px`;
|
endPaddingRef.current.style.height = `${Math.max(
|
||||||
|
newHeight - 50,
|
||||||
|
0
|
||||||
|
)}px`;
|
||||||
|
|
||||||
scrollableDivRef?.current.scrollBy({
|
scrollableDivRef?.current.scrollBy({
|
||||||
left: 0,
|
left: 0,
|
||||||
@@ -495,13 +503,15 @@ export function ChatPage({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const clientScrollToBottom = (fast?: boolean) => {
|
const clientScrollToBottom = (fast?: boolean) => {
|
||||||
setTimeout(
|
setTimeout(() => {
|
||||||
() => {
|
if (fast) {
|
||||||
|
endDivRef.current?.scrollIntoView();
|
||||||
|
} else {
|
||||||
endDivRef.current?.scrollIntoView({ behavior: "smooth" });
|
endDivRef.current?.scrollIntoView({ behavior: "smooth" });
|
||||||
setHasPerformedInitialScroll(true);
|
}
|
||||||
},
|
|
||||||
fast ? 50 : 500
|
setHasPerformedInitialScroll(true);
|
||||||
);
|
}, 50);
|
||||||
};
|
};
|
||||||
|
|
||||||
const isCancelledRef = useRef<boolean>(isCancelled); // scroll is cancelled
|
const isCancelledRef = useRef<boolean>(isCancelled); // scroll is cancelled
|
||||||
@@ -521,13 +531,9 @@ export function ChatPage({
|
|||||||
debounce,
|
debounce,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [hasPerformedInitialScroll, setHasPerformedInitialScroll] =
|
const [hasPerformedInitialScroll, setHasPerformedInitialScroll] = useState(
|
||||||
useState(false);
|
existingChatSessionId === null
|
||||||
|
);
|
||||||
// on new page
|
|
||||||
useEffect(() => {
|
|
||||||
clientScrollToBottom();
|
|
||||||
}, [chatSessionId]);
|
|
||||||
|
|
||||||
// handle re-sizing of the text area
|
// handle re-sizing of the text area
|
||||||
const textAreaRef = useRef<HTMLTextAreaElement>(null);
|
const textAreaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
@@ -639,7 +645,7 @@ export function ChatPage({
|
|||||||
|
|
||||||
clientScrollToBottom();
|
clientScrollToBottom();
|
||||||
let currChatSessionId: number;
|
let currChatSessionId: number;
|
||||||
let isNewSession = chatSessionId === null;
|
let isNewSession = chatSessionIdRef.current === null;
|
||||||
const searchParamBasedChatSessionName =
|
const searchParamBasedChatSessionName =
|
||||||
searchParams.get(SEARCH_PARAM_NAMES.TITLE) || null;
|
searchParams.get(SEARCH_PARAM_NAMES.TITLE) || null;
|
||||||
|
|
||||||
@@ -649,18 +655,19 @@ export function ChatPage({
|
|||||||
searchParamBasedChatSessionName
|
searchParamBasedChatSessionName
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
currChatSessionId = chatSessionId as number;
|
currChatSessionId = chatSessionIdRef.current as number;
|
||||||
}
|
}
|
||||||
setChatSessionId(currChatSessionId);
|
chatSessionIdRef.current = currChatSessionId;
|
||||||
|
|
||||||
const messageToResend = messageHistory.find(
|
const messageToResend = messageHistory.find(
|
||||||
(message) => message.messageId === messageIdToResend
|
(message) => message.messageId === messageIdToResend
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const messageMap = completeMessageDetail.messageMap;
|
||||||
const messageToResendParent =
|
const messageToResendParent =
|
||||||
messageToResend?.parentMessageId !== null &&
|
messageToResend?.parentMessageId !== null &&
|
||||||
messageToResend?.parentMessageId !== undefined
|
messageToResend?.parentMessageId !== undefined
|
||||||
? completeMessageMap.get(messageToResend.parentMessageId)
|
? messageMap.get(messageToResend.parentMessageId)
|
||||||
: null;
|
: null;
|
||||||
const messageToResendIndex = messageToResend
|
const messageToResendIndex = messageToResend
|
||||||
? messageHistory.indexOf(messageToResend)
|
? messageHistory.indexOf(messageToResend)
|
||||||
@@ -687,9 +694,7 @@ export function ChatPage({
|
|||||||
(currMessageHistory.length > 0
|
(currMessageHistory.length > 0
|
||||||
? currMessageHistory[currMessageHistory.length - 1]
|
? currMessageHistory[currMessageHistory.length - 1]
|
||||||
: null) ||
|
: null) ||
|
||||||
(completeMessageMap.size === 1
|
(messageMap.size === 1 ? Array.from(messageMap.values())[0] : null);
|
||||||
? Array.from(completeMessageMap.values())[0]
|
|
||||||
: null);
|
|
||||||
|
|
||||||
// if we're resending, set the parent's child to null
|
// if we're resending, set the parent's child to null
|
||||||
// we will use tempMessages until the regenerated message is complete
|
// we will use tempMessages until the regenerated message is complete
|
||||||
@@ -712,14 +717,16 @@ export function ChatPage({
|
|||||||
latestChildMessageId: TEMP_USER_MESSAGE_ID,
|
latestChildMessageId: TEMP_USER_MESSAGE_ID,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const frozenCompleteMessageMap = upsertToCompleteMessageMap({
|
const { messageMap: frozenMessageMap, sessionId: frozenSessionId } =
|
||||||
messages: messageUpdates,
|
upsertToCompleteMessageMap({
|
||||||
});
|
messages: messageUpdates,
|
||||||
|
chatSessionId: currChatSessionId,
|
||||||
|
});
|
||||||
|
|
||||||
// on initial message send, we insert a dummy system message
|
// on initial message send, we insert a dummy system message
|
||||||
// set this as the parent here if no parent is set
|
// set this as the parent here if no parent is set
|
||||||
if (!parentMessage && frozenCompleteMessageMap.size === 2) {
|
if (!parentMessage && frozenMessageMap.size === 2) {
|
||||||
parentMessage = frozenCompleteMessageMap.get(SYSTEM_MESSAGE_ID) || null;
|
parentMessage = frozenMessageMap.get(SYSTEM_MESSAGE_ID) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentAssistantId = alternativeAssistant
|
const currentAssistantId = alternativeAssistant
|
||||||
@@ -791,7 +798,8 @@ export function ChatPage({
|
|||||||
upsertToCompleteMessageMap({
|
upsertToCompleteMessageMap({
|
||||||
messages: messages,
|
messages: messages,
|
||||||
replacementsMap: replacementsMap,
|
replacementsMap: replacementsMap,
|
||||||
completeMessageMapOverride: frozenCompleteMessageMap,
|
completeMessageMapOverride: frozenMessageMap,
|
||||||
|
chatSessionId: frozenSessionId!,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const delay = (ms: number) => {
|
const delay = (ms: number) => {
|
||||||
@@ -898,7 +906,7 @@ export function ChatPage({
|
|||||||
parentMessageId: TEMP_USER_MESSAGE_ID,
|
parentMessageId: TEMP_USER_MESSAGE_ID,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
completeMessageMapOverride: frozenCompleteMessageMap,
|
completeMessageMapOverride: frozenMessageMap,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setIsStreaming(false);
|
setIsStreaming(false);
|
||||||
@@ -912,12 +920,13 @@ export function ChatPage({
|
|||||||
|
|
||||||
// NOTE: don't switch pages if the user has navigated away from the chat
|
// NOTE: don't switch pages if the user has navigated away from the chat
|
||||||
if (
|
if (
|
||||||
currChatSessionId === urlChatSessionId.current ||
|
currChatSessionId === chatSessionIdRef.current ||
|
||||||
urlChatSessionId.current === null
|
chatSessionIdRef.current === null
|
||||||
) {
|
) {
|
||||||
router.push(buildChatUrl(searchParams, currChatSessionId, null), {
|
const newUrl = buildChatUrl(searchParams, currChatSessionId, null);
|
||||||
scroll: false,
|
// newUrl is like /chat?chatId=10
|
||||||
});
|
// current page is like /chat
|
||||||
|
router.push(newUrl, { scroll: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
@@ -936,7 +945,7 @@ export function ChatPage({
|
|||||||
feedbackDetails: string,
|
feedbackDetails: string,
|
||||||
predefinedFeedback: string | undefined
|
predefinedFeedback: string | undefined
|
||||||
) => {
|
) => {
|
||||||
if (chatSessionId === null) {
|
if (chatSessionIdRef.current === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1074,7 +1083,7 @@ export function ChatPage({
|
|||||||
setEditingRetrievalEnabled(false);
|
setEditingRetrievalEnabled(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
console.log(hasPerformedInitialScroll);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<HealthCheckBanner />
|
<HealthCheckBanner />
|
||||||
@@ -1110,9 +1119,9 @@ export function ChatPage({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{sharingModalVisible && chatSessionId !== null && (
|
{sharingModalVisible && chatSessionIdRef.current !== null && (
|
||||||
<ShareChatSessionModal
|
<ShareChatSessionModal
|
||||||
chatSessionId={chatSessionId}
|
chatSessionId={chatSessionIdRef.current}
|
||||||
existingSharedStatus={chatSessionSharedStatus}
|
existingSharedStatus={chatSessionSharedStatus}
|
||||||
onClose={() => setSharingModalVisible(false)}
|
onClose={() => setSharingModalVisible(false)}
|
||||||
onShare={(shared) =>
|
onShare={(shared) =>
|
||||||
@@ -1126,7 +1135,7 @@ export function ChatPage({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<ConfigurationModal
|
<ConfigurationModal
|
||||||
chatSessionId={chatSessionId!}
|
chatSessionId={chatSessionIdRef.current!}
|
||||||
activeTab={configModalActiveTab}
|
activeTab={configModalActiveTab}
|
||||||
setActiveTab={setConfigModalActiveTab}
|
setActiveTab={setConfigModalActiveTab}
|
||||||
onClose={() => setConfigModalActiveTab(null)}
|
onClose={() => setConfigModalActiveTab(null)}
|
||||||
@@ -1174,7 +1183,7 @@ export function ChatPage({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="ml-auto mr-6 flex">
|
<div className="ml-auto mr-6 flex">
|
||||||
{chatSessionId !== null && (
|
{chatSessionIdRef.current !== null && (
|
||||||
<div
|
<div
|
||||||
onClick={() => setSharingModalVisible(true)}
|
onClick={() => setSharingModalVisible(true)}
|
||||||
className={`
|
className={`
|
||||||
@@ -1221,12 +1230,14 @@ export function ChatPage({
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
{messageHistory.map((message, i) => {
|
{messageHistory.map((message, i) => {
|
||||||
|
const messageMap = completeMessageDetail.messageMap;
|
||||||
|
const messageReactComponentKey = `${i}-${completeMessageDetail.sessionId}`;
|
||||||
if (message.type === "user") {
|
if (message.type === "user") {
|
||||||
const parentMessage = message.parentMessageId
|
const parentMessage = message.parentMessageId
|
||||||
? completeMessageMap.get(message.parentMessageId)
|
? messageMap.get(message.parentMessageId)
|
||||||
: null;
|
: null;
|
||||||
return (
|
return (
|
||||||
<div key={`${i}-${existingChatSessionId}`}>
|
<div key={messageReactComponentKey}>
|
||||||
<HumanMessage
|
<HumanMessage
|
||||||
content={message.message}
|
content={message.message}
|
||||||
files={message.files}
|
files={message.files}
|
||||||
@@ -1238,7 +1249,7 @@ export function ChatPage({
|
|||||||
const parentMessageId =
|
const parentMessageId =
|
||||||
message.parentMessageId!;
|
message.parentMessageId!;
|
||||||
const parentMessage =
|
const parentMessage =
|
||||||
completeMessageMap.get(parentMessageId)!;
|
messageMap.get(parentMessageId)!;
|
||||||
upsertToCompleteMessageMap({
|
upsertToCompleteMessageMap({
|
||||||
messages: [
|
messages: [
|
||||||
{
|
{
|
||||||
@@ -1255,14 +1266,16 @@ export function ChatPage({
|
|||||||
}}
|
}}
|
||||||
onMessageSelection={(messageId) => {
|
onMessageSelection={(messageId) => {
|
||||||
const newCompleteMessageMap = new Map(
|
const newCompleteMessageMap = new Map(
|
||||||
completeMessageMap
|
messageMap
|
||||||
);
|
);
|
||||||
newCompleteMessageMap.get(
|
newCompleteMessageMap.get(
|
||||||
message.parentMessageId!
|
message.parentMessageId!
|
||||||
)!.latestChildMessageId = messageId;
|
)!.latestChildMessageId = messageId;
|
||||||
setCompleteMessageMap(
|
setCompleteMessageDetail({
|
||||||
newCompleteMessageMap
|
sessionId:
|
||||||
);
|
completeMessageDetail.sessionId,
|
||||||
|
messageMap: newCompleteMessageMap,
|
||||||
|
});
|
||||||
setSelectedMessageForDocDisplay(messageId);
|
setSelectedMessageForDocDisplay(messageId);
|
||||||
// set message as latest so we can edit this message
|
// set message as latest so we can edit this message
|
||||||
// and so it sticks around on page reload
|
// and so it sticks around on page reload
|
||||||
@@ -1292,7 +1305,7 @@ export function ChatPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={`${i}-${existingChatSessionId}`}
|
key={messageReactComponentKey}
|
||||||
ref={
|
ref={
|
||||||
i == messageHistory.length - 1
|
i == messageHistory.length - 1
|
||||||
? lastMessageRef
|
? lastMessageRef
|
||||||
@@ -1414,7 +1427,7 @@ export function ChatPage({
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div key={`${i}-${existingChatSessionId}`}>
|
<div key={messageReactComponentKey}>
|
||||||
<AIMessage
|
<AIMessage
|
||||||
currentPersona={livePersona}
|
currentPersona={livePersona}
|
||||||
messageId={message.messageId}
|
messageId={message.messageId}
|
||||||
@@ -1434,7 +1447,7 @@ export function ChatPage({
|
|||||||
messageHistory[messageHistory.length - 1].type ===
|
messageHistory[messageHistory.length - 1].type ===
|
||||||
"user" && (
|
"user" && (
|
||||||
<div
|
<div
|
||||||
key={`${messageHistory.length}-${existingChatSessionId}`}
|
key={`${messageHistory.length}-${chatSessionIdRef.current}`}
|
||||||
>
|
>
|
||||||
<AIMessage
|
<AIMessage
|
||||||
currentPersona={livePersona}
|
currentPersona={livePersona}
|
||||||
|
@@ -385,7 +385,9 @@ export function processRawChatHistory(
|
|||||||
message: messageInfo.message,
|
message: messageInfo.message,
|
||||||
type: messageInfo.message_type as "user" | "assistant",
|
type: messageInfo.message_type as "user" | "assistant",
|
||||||
files: messageInfo.files,
|
files: messageInfo.files,
|
||||||
alternateAssistantID: Number(messageInfo.alternate_assistant_id),
|
alternateAssistantID: messageInfo.alternate_assistant_id
|
||||||
|
? Number(messageInfo.alternate_assistant_id)
|
||||||
|
: null,
|
||||||
// only include these fields if this is an assistant message so that
|
// only include these fields if this is an assistant message so that
|
||||||
// this is identical to what is computed at streaming time
|
// this is identical to what is computed at streaming time
|
||||||
...(messageInfo.message_type === "assistant"
|
...(messageInfo.message_type === "assistant"
|
||||||
|
@@ -25,6 +25,11 @@ export function CodeBlock({
|
|||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
if (!language) {
|
if (!language) {
|
||||||
|
// this is the case of a single "`" e.g. `hi`
|
||||||
|
if (typeof children === "string") {
|
||||||
|
return <code className={className}>{children}</code>;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<pre style={CODE_BLOCK_PADDING_TYPE}>
|
<pre style={CODE_BLOCK_PADDING_TYPE}>
|
||||||
<code {...props} className={`text-sm ${className}`}>
|
<code {...props} className={`text-sm ${className}`}>
|
||||||
|
@@ -150,8 +150,7 @@ export const AIMessage = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const shouldShowLoader =
|
const shouldShowLoader =
|
||||||
!toolCall ||
|
!toolCall || (toolCall.tool_name === SEARCH_TOOL_NAME && !content);
|
||||||
(toolCall.tool_name === SEARCH_TOOL_NAME && query === undefined);
|
|
||||||
const defaultLoader = shouldShowLoader ? (
|
const defaultLoader = shouldShowLoader ? (
|
||||||
<div className="text-sm my-auto">
|
<div className="text-sm my-auto">
|
||||||
<ThreeDots
|
<ThreeDots
|
||||||
|
Reference in New Issue
Block a user