mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-25 19:56:13 +01:00
* ✨ feat: Add Expand Chat functionality and improve UI components * ✨ feat: Introduce Chat Badges feature with editing capabilities and UI enhancements * ✨ feat: re-implement file attachment functionality with new components and improved UI * ✨ feat: Enhance BadgeRow component with drag-and-drop functionality and add animations for better user experience * ✨ feat: Add useChatBadges hook and enhance Badge component with animations and toggle functionality * feat: Improve Add/Delete Badges + style and bug fixes * ✨ feat: Refactor EditBadges component and optimize useChatBadges hook for improved performance and readability * ✨ feat: Add type definition for LucideIcon in EditBadges component * refactor: Clean up BadgeRow component by removing outdated comment and improving code readability * refactor: Rename app-icon class to badge-icon for consistency and improve badge styling * feat: Add Center Chat Input toggle and update related components for improved UI/UX * refactor: Simplify ChatView and MessagesView components for improved readability and performance * refactor: Improve layout and positioning of scroll button in MessagesView component * refactor: Adjust scroll button position in MessagesView component for better visibility * refactor: Remove redundant background class from Badge component for cleaner styling * feat: disable chat badges * refactor: adjust positioning of scroll button and popover for improved layout * refactor: simplify class names in ChatForm and RemoveFile components for cleaner code * refactor: move Switcher to HeaderOptions from SidePanel * fix(Landing): duplicate description * feat: add SplitText component for animated text display and update Landing component to use it * feat(Chat): add ConversationStarters component and integrate it into ChatView; remove ConvoStarter component * feat(Chat): enhance Message component layout and styling for improved readability * feat(ControlCombobox, Select): enhance styling and add animation for improved UI experience * feat(Chat): update Header and HeaderNewChat components for improved layout and styling * feat(Chat): add ModelDropdown (now includes both endpoint and model) and refactor Menu components for improved UI * feat(ModelDropdown): add Agent Select; removed old AgentSwitcher components * feat(ModelDropdown): add settings button for user key configuration * fix(ModelDropdown): the model dropdown wasn't opening automatically when opening the endpoint one * refactor(Chat): remove unused EndpointsMenu and related components to streamline codebase * feat: enhance greeting message and improve accessibility fro ModelDropdown * refactor(Endpoints): add new hooks and components for endpoint management * feat(Endpoint): add support for modelSpecs * feat(Endpoints): add mobile support * fix: type issues * fix(modelSpec): type issue * fix(EndpointMenuDropdown): double overflow scroller in mobile model list * fix: search model on mobile * refactor: Endpoint/Model/modelSpec dropdown * refactor: reorganize imports in Endpoint components * refactor: remove unused translation keys from English locale * BREAKING: moving to ariakit with new CustomMenu * refactor: remove unnecessary comments * refactor: remove EndpointItem, ModelDropdownButton, SpecIcon, and SpecItem components * 🔧 fix: AI Icon bump when regenerating message * wip: chat UI refactoring, fix issues * chore: add recent update to useAutoSave * feat: add access control for agent permissions in useMentions hook * refactor: streamline ModelSelector by removing unused endpoints logic * refactor: enhance ModelSelector and context by integrating endpointsConfig and improving type usage * feat: update ModelSelectorContext to utilize conversation data for initial state * feat: add selector effects for synced endpoint handling * feat: add guard clause for conversation endpoint in useSelectorEffects hook * fix: safely call onSelectMention and add autofocus to mention input * chore: typing * refactor: ModelSelector to streamline key dialog handling and improve endpoint rendering * refactor: extract SettingsButton component for cleaner endpoint item rendering * wip: first pass, expand set api key * wip: first pass, expanding set key * refactor: update EndpointItem styles for improved layout and hover effects * refactor: adjust padding in EndpointItem for improved layout consistency * refactor: update preset structure in useSelectMention to include spec as null * refactor: rename setKeyDialogOpen to onOpenChange for clarity and consistency, bring focus back to button that opened dialog * feat: add SpecIcon component for dynamic model spec icons in menu, adjust icon styling * refactor: update getSelectedIcon to accept additional parameters and improve icon rendering logic * fix: adjust padding in MessageRender for improved layout * refactor: remove inline style for menu width in CustomMenu component * refactor: enhance layout and styling in ModelSpecItem component for better responsiveness * refactor: update getDefaultModelSpec to accept startupConfig and improve model spec retrieval logic * refactor: improve key management and default values in ModelSelector and related components * refactor: adjust menu width and improve responsiveness in CustomMenu and EndpointItem components * refactor: enhance focus styles and responsiveness in EndpointItem component * refactor: improve layout and spacing in Header and ModelSelector components for better responsiveness * refactor: adjust button styles for consistency and improved layout in AddMultiConvo and PresetsMenu components * fix: initial fix of assistant names * fix: assistants handling * chore: update version of librechat-data-provider to 0.7.75 and add 'spec' to excludedKeys * fix: improve endpoint filtering logic based on interface configuration and access rights * fix: remove unused HeaderOptions import and set spec to null in presets and mentions * fix: ensure currentExample is always an object when updating examples * fix: update interfaceConfig checks to ensure modelSelect is considered for rendering components * fix: update model selection logic to consider interface configuration when prioritizing model specs * fix: add missing localizations * fix: remove unused agent and assistant selection translations * fix: implement debounced state updates for selected values in useSelectorEffects * style: minor style changes related to the ModelSelector * fix: adjust maximum height for popover and set fixed height for model item * fix: update placeholders for model and endpoint search inputs * fix: refactor MessageRender and ContentRender components to better match each other * fix: remove convo fallback for iconURL in MessageRender and ContentRender components * fix: update handling of spec, iconURL, and modelLabel in conversation presets, to allow better interchangeability * fix: replace chatGptLabel with modelLabel in OpenAI settings configuration (fully deprecate chatGptLabel) * fix: remove console log for assistantNames in useEndpoints hook * refactor: add cleanInput and cleanOutput options to default conversation handling * chore: update bun.lockb * fix: set default value for showIconInHeader in getSelectedIcon function * refactor: enhance error handling in message processing when latest message has existing content blocks * chore: allow import/no-cycle for messages * fix: adjust flex properties in BookmarkMenu for better layout * feat: support both 'prompt' and 'q' as query parameters in useQueryParams hook * feat: re-enable Badges components * refactor: disable edit badge component * chore: rename assistantMap to assistantsMap for consistency * chore: rename assistantMap to assistantsMap for consistency in Mention component * feat: set staleTime for various queries to improve data freshness * feat: add spec field to tQueryParamsSchema for model specification * feat: enhance useQueryParams to handle model specs --------- Co-authored-by: Danny Avila <danny@librechat.ai>
186 lines
5.7 KiB
TypeScript
186 lines
5.7 KiB
TypeScript
import {
|
|
Tools,
|
|
ContentTypes,
|
|
ToolCallTypes,
|
|
imageGenTools,
|
|
isImageVisionTool,
|
|
} from 'librechat-data-provider';
|
|
import { memo } from 'react';
|
|
import type { TMessageContentParts, TAttachment } from 'librechat-data-provider';
|
|
import { ErrorMessage } from './MessageContent';
|
|
import AgentUpdate from './Parts/AgentUpdate';
|
|
import ExecuteCode from './Parts/ExecuteCode';
|
|
import RetrievalCall from './RetrievalCall';
|
|
import Reasoning from './Parts/Reasoning';
|
|
import EmptyText from './Parts/EmptyText';
|
|
import CodeAnalyze from './CodeAnalyze';
|
|
import Container from './Container';
|
|
import ToolCall from './ToolCall';
|
|
import ImageGen from './ImageGen';
|
|
import Text from './Parts/Text';
|
|
import Image from './Image';
|
|
|
|
type PartProps = {
|
|
part?: TMessageContentParts;
|
|
isLast?: boolean;
|
|
isSubmitting: boolean;
|
|
showCursor: boolean;
|
|
isCreatedByUser: boolean;
|
|
attachments?: TAttachment[];
|
|
};
|
|
|
|
const Part = memo(
|
|
({ part, isSubmitting, attachments, isLast, showCursor, isCreatedByUser }: PartProps) => {
|
|
if (!part) {
|
|
return null;
|
|
}
|
|
|
|
if (part.type === ContentTypes.ERROR) {
|
|
return (
|
|
<ErrorMessage
|
|
text={
|
|
part[ContentTypes.ERROR] ??
|
|
(typeof part[ContentTypes.TEXT] === 'string'
|
|
? part[ContentTypes.TEXT]
|
|
: part.text?.value) ??
|
|
''
|
|
}
|
|
className="my-2"
|
|
/>
|
|
);
|
|
} else if (part.type === ContentTypes.AGENT_UPDATE) {
|
|
return (
|
|
<>
|
|
<AgentUpdate currentAgentId={part[ContentTypes.AGENT_UPDATE]?.agentId} />
|
|
{isLast && showCursor && (
|
|
<Container>
|
|
<EmptyText />
|
|
</Container>
|
|
)}
|
|
</>
|
|
);
|
|
} else if (part.type === ContentTypes.TEXT) {
|
|
const text = typeof part.text === 'string' ? part.text : part.text.value;
|
|
|
|
if (typeof text !== 'string') {
|
|
return null;
|
|
}
|
|
if (part.tool_call_ids != null && !text) {
|
|
return null;
|
|
}
|
|
return (
|
|
<Container>
|
|
<Text text={text} isCreatedByUser={isCreatedByUser} showCursor={showCursor} />
|
|
</Container>
|
|
);
|
|
} else if (part.type === ContentTypes.THINK) {
|
|
const reasoning = typeof part.think === 'string' ? part.think : part.think.value;
|
|
if (typeof reasoning !== 'string') {
|
|
return null;
|
|
}
|
|
return <Reasoning reasoning={reasoning} />;
|
|
} else if (part.type === ContentTypes.TOOL_CALL) {
|
|
const toolCall = part[ContentTypes.TOOL_CALL];
|
|
|
|
if (!toolCall) {
|
|
return null;
|
|
}
|
|
|
|
const isToolCall =
|
|
'args' in toolCall && (!toolCall.type || toolCall.type === ToolCallTypes.TOOL_CALL);
|
|
if (isToolCall && toolCall.name === Tools.execute_code) {
|
|
return (
|
|
<ExecuteCode
|
|
args={typeof toolCall.args === 'string' ? toolCall.args : ''}
|
|
output={toolCall.output ?? ''}
|
|
initialProgress={toolCall.progress ?? 0.1}
|
|
isSubmitting={isSubmitting}
|
|
attachments={attachments}
|
|
/>
|
|
);
|
|
} else if (isToolCall) {
|
|
return (
|
|
<ToolCall
|
|
args={toolCall.args ?? ''}
|
|
name={toolCall.name || ''}
|
|
output={toolCall.output ?? ''}
|
|
initialProgress={toolCall.progress ?? 0.1}
|
|
isSubmitting={isSubmitting}
|
|
attachments={attachments}
|
|
auth={toolCall.auth}
|
|
expires_at={toolCall.expires_at}
|
|
/>
|
|
);
|
|
} else if (toolCall.type === ToolCallTypes.CODE_INTERPRETER) {
|
|
const code_interpreter = toolCall[ToolCallTypes.CODE_INTERPRETER];
|
|
return (
|
|
<CodeAnalyze
|
|
initialProgress={toolCall.progress ?? 0.1}
|
|
code={code_interpreter.input}
|
|
outputs={code_interpreter.outputs ?? []}
|
|
isSubmitting={isSubmitting}
|
|
/>
|
|
);
|
|
} else if (
|
|
toolCall.type === ToolCallTypes.RETRIEVAL ||
|
|
toolCall.type === ToolCallTypes.FILE_SEARCH
|
|
) {
|
|
return (
|
|
<RetrievalCall initialProgress={toolCall.progress ?? 0.1} isSubmitting={isSubmitting} />
|
|
);
|
|
} else if (
|
|
toolCall.type === ToolCallTypes.FUNCTION &&
|
|
ToolCallTypes.FUNCTION in toolCall &&
|
|
imageGenTools.has(toolCall.function.name)
|
|
) {
|
|
return (
|
|
<ImageGen
|
|
initialProgress={toolCall.progress ?? 0.1}
|
|
args={toolCall.function.arguments as string}
|
|
/>
|
|
);
|
|
} else if (toolCall.type === ToolCallTypes.FUNCTION && ToolCallTypes.FUNCTION in toolCall) {
|
|
if (isImageVisionTool(toolCall)) {
|
|
if (isSubmitting && showCursor) {
|
|
return (
|
|
<Container>
|
|
<Text text={''} isCreatedByUser={isCreatedByUser} showCursor={showCursor} />
|
|
</Container>
|
|
);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<ToolCall
|
|
initialProgress={toolCall.progress ?? 0.1}
|
|
isSubmitting={isSubmitting}
|
|
args={toolCall.function.arguments as string}
|
|
name={toolCall.function.name}
|
|
output={toolCall.function.output}
|
|
/>
|
|
);
|
|
}
|
|
} else if (part.type === ContentTypes.IMAGE_FILE) {
|
|
const imageFile = part[ContentTypes.IMAGE_FILE];
|
|
const height = imageFile.height ?? 1920;
|
|
const width = imageFile.width ?? 1080;
|
|
return (
|
|
<Image
|
|
imagePath={imageFile.filepath}
|
|
height={height}
|
|
width={width}
|
|
altText={imageFile.filename ?? 'Uploaded Image'}
|
|
placeholderDimensions={{
|
|
height: height + 'px',
|
|
width: width + 'px',
|
|
}}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return null;
|
|
},
|
|
);
|
|
|
|
export default Part;
|