diff --git a/client/src/components/Agents/AgentCard.tsx b/client/src/components/Agents/AgentCard.tsx index 6a81a1645e..d528bff36b 100644 --- a/client/src/components/Agents/AgentCard.tsx +++ b/client/src/components/Agents/AgentCard.tsx @@ -2,7 +2,7 @@ import React, { useMemo } from 'react'; import { Label } from '@librechat/client'; import type t from 'librechat-data-provider'; import { useLocalize, TranslationKeys, useAgentCategories } from '~/hooks'; -import { cn, renderAgentAvatar, getContactDisplayName } from '~/utils'; +import { cn, AgentAvatar, getContactDisplayName } from '~/utils'; interface AgentCardProps { agent: t.Agent; // The agent data to display @@ -59,7 +59,9 @@ const AgentCard: React.FC = ({ agent, onClick, className = '' })
{/* Left column: Avatar and Category */}
-
{renderAgentAvatar(agent, { size: 'sm' })}
+
+ +
{/* Category tag */} {agent.category && ( diff --git a/client/src/components/Agents/AgentDetail.tsx b/client/src/components/Agents/AgentDetail.tsx index 1820eed8b9..b87424a07d 100644 --- a/client/src/components/Agents/AgentDetail.tsx +++ b/client/src/components/Agents/AgentDetail.tsx @@ -12,7 +12,7 @@ import { } from 'librechat-data-provider'; import type t from 'librechat-data-provider'; import { useLocalize, useDefaultConvo, useFavorites } from '~/hooks'; -import { renderAgentAvatar, clearMessagesCache } from '~/utils'; +import { AgentAvatar, clearMessagesCache } from '~/utils'; import { useChatContext } from '~/Providers'; interface SupportContact { @@ -142,7 +142,9 @@ const AgentDetail: React.FC = ({ agent, isOpen, onClose }) => !open && onClose()}> {/* Agent avatar */} -
{renderAgentAvatar(agent, { size: 'xl' })}
+
+ +
{/* Agent name */}
diff --git a/client/src/components/Agents/tests/Accessibility.spec.tsx b/client/src/components/Agents/tests/Accessibility.spec.tsx index 9718497769..36138db5a2 100644 --- a/client/src/components/Agents/tests/Accessibility.spec.tsx +++ b/client/src/components/Agents/tests/Accessibility.spec.tsx @@ -105,7 +105,7 @@ jest.mock('~/data-provider/Agents', () => ({ // Mock utility functions jest.mock('~/utils/agents', () => ({ - renderAgentAvatar: jest.fn(() =>
), + AgentAvatar: jest.fn(() =>
), getContactDisplayName: jest.fn((agent) => agent.authorName), })); diff --git a/client/src/components/Agents/tests/AgentDetail.spec.tsx b/client/src/components/Agents/tests/AgentDetail.spec.tsx index 0a1afffea7..5ce1418438 100644 --- a/client/src/components/Agents/tests/AgentDetail.spec.tsx +++ b/client/src/components/Agents/tests/AgentDetail.spec.tsx @@ -46,9 +46,7 @@ jest.mock('@librechat/client', () => ({ })); jest.mock('~/utils/agents', () => ({ - renderAgentAvatar: jest.fn((agent, options) => ( -
- )), + AgentAvatar: jest.fn(({ agent, size }) =>
), })); jest.mock('~/Providers', () => ({ diff --git a/client/src/components/Endpoints/EndpointIcon.tsx b/client/src/components/Endpoints/EndpointIcon.tsx index 9e4f2bb6a7..ba2cbf6993 100644 --- a/client/src/components/Endpoints/EndpointIcon.tsx +++ b/client/src/components/Endpoints/EndpointIcon.tsx @@ -41,7 +41,9 @@ export default function EndpointIcon({ const assistantName = assistant && (assistant.name ?? ''); const agent = - endpoint === EModelEndpoint.agents ? agentsMap?.[conversation?.agent_id ?? ''] : null; + endpoint === EModelEndpoint.agents && conversation?.agent_id + ? agentsMap?.[conversation.agent_id] + : null; const agentAvatar = getAgentAvatarUrl(agent) ?? ''; const iconURL = assistantAvatar || agentAvatar || convoIconURL; diff --git a/client/src/components/Nav/Favorites/FavoriteItem.tsx b/client/src/components/Nav/Favorites/FavoriteItem.tsx index 74418e71fb..be3d770f29 100644 --- a/client/src/components/Nav/Favorites/FavoriteItem.tsx +++ b/client/src/components/Nav/Favorites/FavoriteItem.tsx @@ -8,7 +8,7 @@ import type { FavoriteModel } from '~/store/favorites'; import type t from 'librechat-data-provider'; import EndpointIcon from '~/components/Endpoints/EndpointIcon'; import { useNewConvo, useFavorites, useLocalize } from '~/hooks'; -import { renderAgentAvatar, cn } from '~/utils'; +import { AgentAvatar, cn } from '~/utils'; type FavoriteItemProps = { item: t.Agent | FavoriteModel; @@ -71,7 +71,7 @@ export default function FavoriteItem({ item, type }: FavoriteItemProps) { const renderIcon = () => { if (type === 'agent') { - return renderAgentAvatar(item as t.Agent, { size: 'icon', className: 'mr-2' }); + return ; } const model = item as FavoriteModel; return ( diff --git a/client/src/locales/en/translation.json b/client/src/locales/en/translation.json index e97f74ad68..06dd3ff9a5 100644 --- a/client/src/locales/en/translation.json +++ b/client/src/locales/en/translation.json @@ -865,7 +865,6 @@ "com_ui_date_yesterday": "Yesterday", "com_ui_decline": "I do not accept", "com_ui_default_post_request": "Default (POST request)", - "com_ui_unpin": "Unpin", "com_ui_delete": "Delete", "com_ui_delete_action": "Delete Action", "com_ui_delete_action_confirm": "Are you sure you want to delete this action?", diff --git a/client/src/utils/__tests__/agents.spec.tsx b/client/src/utils/__tests__/agents.spec.tsx index dee58cdf84..30590863fb 100644 --- a/client/src/utils/__tests__/agents.spec.tsx +++ b/client/src/utils/__tests__/agents.spec.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import '@testing-library/jest-dom'; -import { getAgentAvatarUrl, renderAgentAvatar, getContactDisplayName } from '../agents'; +import { getAgentAvatarUrl, AgentAvatar, getContactDisplayName } from '../agents'; import type t from 'librechat-data-provider'; // Mock the Feather icon from lucide-react @@ -61,7 +61,7 @@ describe('Agent Utilities', () => { }); }); - describe('renderAgentAvatar', () => { + describe('AgentAvatar', () => { it('should render image when avatar URL exists', () => { const agent = { id: '1', @@ -69,7 +69,7 @@ describe('Agent Utilities', () => { avatar: '/test-avatar.png', } as unknown as t.Agent; - render(
{renderAgentAvatar(agent)}
); + render(); const img = screen.getByAltText('Test Agent avatar'); expect(img).toBeInTheDocument(); @@ -83,7 +83,7 @@ describe('Agent Utilities', () => { name: 'Test Agent', } as t.Agent; - render(
{renderAgentAvatar(agent)}
); + render(); const featherIcon = screen.getByTestId('feather-icon'); expect(featherIcon).toBeInTheDocument(); @@ -97,13 +97,13 @@ describe('Agent Utilities', () => { avatar: '/test-avatar.png', } as unknown as t.Agent; - const { rerender } = render(
{renderAgentAvatar(agent, { size: 'sm' })}
); + const { rerender } = render(); expect(screen.getByAltText('Test Agent avatar')).toHaveClass('h-12', 'w-12'); - rerender(
{renderAgentAvatar(agent, { size: 'lg' })}
); + rerender(); expect(screen.getByAltText('Test Agent avatar')).toHaveClass('h-20', 'w-20'); - rerender(
{renderAgentAvatar(agent, { size: 'xl' })}
); + rerender(); expect(screen.getByAltText('Test Agent avatar')).toHaveClass('h-24', 'w-24'); }); @@ -114,7 +114,7 @@ describe('Agent Utilities', () => { avatar: '/test-avatar.png', } as unknown as t.Agent; - render(
{renderAgentAvatar(agent, { className: 'custom-class' })}
); + render(); const container = screen.getByAltText('Test Agent avatar').parentElement; expect(container).toHaveClass('custom-class'); @@ -127,10 +127,10 @@ describe('Agent Utilities', () => { avatar: '/test-avatar.png', } as unknown as t.Agent; - const { rerender } = render(
{renderAgentAvatar(agent, { showBorder: true })}
); + const { rerender } = render(); expect(screen.getByAltText('Test Agent avatar')).toHaveClass('border-1'); - rerender(
{renderAgentAvatar(agent, { showBorder: false })}
); + rerender(); expect(screen.getByAltText('Test Agent avatar')).not.toHaveClass('border-1'); }); }); diff --git a/client/src/utils/agents.tsx b/client/src/utils/agents.tsx index a65577d1f3..1951f7549c 100644 --- a/client/src/utils/agents.tsx +++ b/client/src/utils/agents.tsx @@ -85,16 +85,17 @@ const LazyAgentAvatar = ({ * Renders an agent avatar with fallback to Bot icon * Consistent across all agent displays */ -export const renderAgentAvatar = ( - agent: t.Agent | null | undefined, - options: { - size?: 'icon' | 'sm' | 'md' | 'lg' | 'xl'; - className?: string; - showBorder?: boolean; - } = {}, -): React.ReactElement => { - const { size = 'md', className = '', showBorder = true } = options; - +export const AgentAvatar = ({ + agent, + size = 'md', + className = '', + showBorder = true, +}: { + agent: t.Agent | null | undefined; + size?: 'icon' | 'sm' | 'md' | 'lg' | 'xl'; + className?: string; + showBorder?: boolean; +}) => { const avatarUrl = getAgentAvatarUrl(agent); // Size mappings for responsive design