mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-27 13:48:51 +01:00
* wip: Add Instructions component for agent configuration
* ✨ feat: Implement DropdownPopup for variable insertion in instructions
* refactor: Enhance variable handling by exporting specialVariables and updating Markdown components
* feat: Add special variable support for current date and user in Instructions component
* refactor: Update handleAddVariable to include localized label
* feat: replace special variables in instructions presets
* chore: update parameter type for user in getListAgents function
* refactor: integrate dayjs for date handling and move replaceSpecialVars function to data-provider
* feat: enhance replaceSpecialVars to include day number in current date format
* feat: integrate replaceSpecialVars for processing agent instructions
* feat: add support for current date & time in replaceSpecialVars function
* feat: add iso_datetime support in replaceSpecialVars function
* fix: enforce text parameter to be a required field in replaceSpecialVars function
* feat: add ISO datetime support in translation file
* fix: disable eslint warning for autoFocus in TextareaAutosize component
* feat: add VariablesDropdown component and integrate it into CreatePromptForm and PromptEditor; update translation for special variables
* fix: CategorySelector and related localizations
* fix: add z-index class to LanguageSTTDropdown for proper stacking context
* fix: add max-height and overflow styles to OGDialogContent in VariableDialog and PreviewPrompt components
* fix: update variable detection logic to exclude special variables and improve regex matching
* fix: improve accessibility text for actions menu in ChatGroupItem component
* fix: adjust max-width and height styles for dialog components and improve markdown rendering for light vs. dark, height/widths, etc.
* fix: remove commented-out code for better readability in PromptVariableGfm component
* fix: handle undefined input parameter in setParams function call
* fix: update variable label types to use TSpecialVarLabel for consistency
* fix: remove outdated information from special variables description in translation file
* fix: enhance unused i18next keys detection for special variable keys
* fix: update color classes for consistency/a11y in category and prompt variable components
* fix: update PromptVariableGfm component and special variable styles for consistency
* fix: improve variable highlighting logic in VariableForm component
* fix: update background color classes for consistency in VariableForm component
* fix: add missing ref parameter to Dialog component in OriginalDialog
* refactor: move navigate call for new conversation to after setConversation update
* refactor: move message query hook to client workspace; fix: handle edge case for navigation from finalHandler creating race condition for response message DB save
* chore: bump librechat-data-provider to 0.7.793
* ci: add unit tests for replaceSpecialVars function
* fix: implement getToolkitKey function for image_gen_oai toolkit filtering/including
* ci: enhance dayjs mock for consistent date/time values in tests
* fix: MCP stdio server fail to start when passing env property
* fix: use optional chaining for clientRef dereferencing in AskController and EditController
feat: add context to saveMessage call in streamResponse utility
* fix: only save error messages if the userMessageId was initialized
* refactor: add isNotAppendable check to disable inputs in ChatForm and useTextarea
* feat: enhance error handling in useEventHandlers and update conversation state in useNewConvo
* refactor: prepend underscore to conversationId in newConversation template
* feat: log aborted conversations with minimal messages and use consistent conversationId generation
---------
Co-authored-by: Olivier Schiavo <olivier.schiavo@wengo.com>
Co-authored-by: aka012 <aka012@neowiz.com>
Co-authored-by: jiasheng <jiashengguo@outlook.com>
114 lines
4.1 KiB
TypeScript
114 lines
4.1 KiB
TypeScript
import { memo, useCallback } from 'react';
|
|
import { useRecoilValue } from 'recoil';
|
|
import { useForm } from 'react-hook-form';
|
|
import { useParams } from 'react-router-dom';
|
|
import { Constants } from 'librechat-data-provider';
|
|
import type { TMessage } from 'librechat-data-provider';
|
|
import type { ChatFormValues } from '~/common';
|
|
import { ChatContext, AddedChatContext, useFileMapContext, ChatFormProvider } from '~/Providers';
|
|
import { useChatHelpers, useAddedResponse, useSSE } from '~/hooks';
|
|
import ConversationStarters from './Input/ConversationStarters';
|
|
import { useGetMessagesByConvoId } from '~/data-provider';
|
|
import MessagesView from './Messages/MessagesView';
|
|
import { Spinner } from '~/components/svg';
|
|
import Presentation from './Presentation';
|
|
import { buildTree, cn } from '~/utils';
|
|
import ChatForm from './Input/ChatForm';
|
|
import Landing from './Landing';
|
|
import Header from './Header';
|
|
import Footer from './Footer';
|
|
import store from '~/store';
|
|
|
|
function LoadingSpinner() {
|
|
return (
|
|
<div className="relative flex-1 overflow-hidden overflow-y-auto">
|
|
<div className="relative flex h-full items-center justify-center">
|
|
<Spinner className="text-text-primary" />
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function ChatView({ index = 0 }: { index?: number }) {
|
|
const { conversationId } = useParams();
|
|
const rootSubmission = useRecoilValue(store.submissionByIndex(index));
|
|
const addedSubmission = useRecoilValue(store.submissionByIndex(index + 1));
|
|
const centerFormOnLanding = useRecoilValue(store.centerFormOnLanding);
|
|
|
|
const fileMap = useFileMapContext();
|
|
|
|
const { data: messagesTree = null, isLoading } = useGetMessagesByConvoId(conversationId ?? '', {
|
|
select: useCallback(
|
|
(data: TMessage[]) => {
|
|
const dataTree = buildTree({ messages: data, fileMap });
|
|
return dataTree?.length === 0 ? null : (dataTree ?? null);
|
|
},
|
|
[fileMap],
|
|
),
|
|
enabled: !!fileMap,
|
|
});
|
|
|
|
const chatHelpers = useChatHelpers(index, conversationId);
|
|
const addedChatHelpers = useAddedResponse({ rootIndex: index });
|
|
|
|
useSSE(rootSubmission, chatHelpers, false);
|
|
useSSE(addedSubmission, addedChatHelpers, true);
|
|
|
|
const methods = useForm<ChatFormValues>({
|
|
defaultValues: { text: '' },
|
|
});
|
|
|
|
let content: JSX.Element | null | undefined;
|
|
const isLandingPage =
|
|
(!messagesTree || messagesTree.length === 0) &&
|
|
(conversationId === Constants.NEW_CONVO || !conversationId);
|
|
const isNavigating = (!messagesTree || messagesTree.length === 0) && conversationId != null;
|
|
|
|
if (isLoading && conversationId !== Constants.NEW_CONVO) {
|
|
content = <LoadingSpinner />;
|
|
} else if ((isLoading || isNavigating) && !isLandingPage) {
|
|
content = <LoadingSpinner />;
|
|
} else if (!isLandingPage) {
|
|
content = <MessagesView messagesTree={messagesTree} />;
|
|
} else {
|
|
content = <Landing centerFormOnLanding={centerFormOnLanding} />;
|
|
}
|
|
|
|
return (
|
|
<ChatFormProvider {...methods}>
|
|
<ChatContext.Provider value={chatHelpers}>
|
|
<AddedChatContext.Provider value={addedChatHelpers}>
|
|
<Presentation>
|
|
<div className="flex h-full w-full flex-col">
|
|
{!isLoading && <Header />}
|
|
<>
|
|
<div
|
|
className={cn(
|
|
'flex flex-col',
|
|
isLandingPage
|
|
? 'flex-1 items-center justify-end sm:justify-center'
|
|
: 'h-full overflow-y-auto',
|
|
)}
|
|
>
|
|
{content}
|
|
<div
|
|
className={cn(
|
|
'w-full',
|
|
isLandingPage && 'max-w-3xl transition-all duration-200 xl:max-w-4xl',
|
|
)}
|
|
>
|
|
<ChatForm index={index} />
|
|
{isLandingPage ? <ConversationStarters /> : <Footer />}
|
|
</div>
|
|
</div>
|
|
{isLandingPage && <Footer />}
|
|
</>
|
|
</div>
|
|
</Presentation>
|
|
</AddedChatContext.Provider>
|
|
</ChatContext.Provider>
|
|
</ChatFormProvider>
|
|
);
|
|
}
|
|
|
|
export default memo(ChatView);
|