LibreChat/client/src/components/SidePanel/Agents/AgentDetail.tsx

219 lines
6.9 KiB
TypeScript
Raw Normal View History

import React, { useRef, useState, useEffect } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import type t from 'librechat-data-provider';
import {
AgentListResponse,
PERMISSION_BITS,
QueryKeys,
Constants,
EModelEndpoint,
LocalStorageKeys,
} from 'librechat-data-provider';
import { useChatContext } from '~/Providers';
import { Dialog, DialogContent, Button } from '~/components/ui';
import { renderAgentAvatar } from '~/utils/agents';
import { DotsIcon } from '~/components/svg';
import { useToast, useLocalize } from '~/hooks';
interface SupportContact {
name?: string;
email?: string;
}
interface AgentWithSupport extends t.Agent {
support_contact?: SupportContact;
}
interface AgentDetailProps {
agent: AgentWithSupport; // The agent data to display
isOpen: boolean; // Whether the detail dialog is open
onClose: () => void; // Callback when dialog is closed
}
/**
* Dialog for displaying agent details
*/
const AgentDetail: React.FC<AgentDetailProps> = ({ agent, isOpen, onClose }) => {
const localize = useLocalize();
// const navigate = useNavigate();
const { conversation, newConversation } = useChatContext();
const { showToast } = useToast();
const dialogRef = useRef<HTMLDivElement>(null);
const dropdownRef = useRef<HTMLDivElement>(null);
const [dropdownOpen, setDropdownOpen] = useState(false);
🔧 fix: Merge and Rebase Conflicts - Move AgentCategory from api/models to @packages/data-schemas structure - Add schema, types, methods, and model following codebase conventions - Implement auto-seeding of default categories during AppService startup - Update marketplace controller to use new data-schemas methods - Remove old model file and standalone seed script refactor: unify agent marketplace to single endpoint with cursor pagination - Replace multiple marketplace routes with unified /marketplace endpoint - Add query string controls: category, search, limit, cursor, promoted, requiredPermission - Implement cursor-based pagination replacing page-based system - Integrate ACL permissions for proper access control - Fix ObjectId constructor error in Agent model - Update React components to use unified useGetMarketplaceAgentsQuery hook - Enhance type safety and remove deprecated useDynamicAgentQuery - Update tests for new marketplace architecture -Known issues: see more button after category switching + Unit tests feat: add icon property to ProcessedAgentCategory interface - Add useMarketplaceAgentsInfiniteQuery and useGetAgentCategoriesQuery to client/src/data-provider/Agents/ - Replace manual pagination in AgentGrid with infinite query pattern - Update imports to use local data provider instead of librechat-data-provider - Add proper permission handling with PERMISSION_BITS.VIEW/EDIT constants - Improve agent access control by adding requiredPermission validation in backend - Remove manual cursor/state management in favor of infinite query built-ins - Maintain existing search and category filtering functionality refactor: consolidate agent marketplace endpoints into main agents API and improve data management consistency - Remove dedicated marketplace controller and routes, merging functionality into main agents v1 API - Add countPromotedAgents function to Agent model for promoted agents count - Enhance getListAgents handler with marketplace filtering (category, search, promoted status) - Move getAgentCategories from marketplace to v1 controller with same functionality - Update agent mutations to invalidate marketplace queries and handle multiple permission levels - Improve cache management by updating all agent query variants (VIEW/EDIT permissions) - Consolidate agent data access patterns for better maintainability and consistency - Remove duplicate marketplace route definitions and middleware selected view only agents injected in the drop down fix: remove minlength validation for support contact name in agent schema feat: add validation and error messages for agent name in AgentConfig and AgentPanel fix: update agent permission check logic in AgentPanel to simplify condition Fix linting WIP Fix Unit tests WIP ESLint fixes eslint fix refactor: enhance isDuplicateVersion function in Agent model for improved comparison logic - Introduced handling for undefined/null values in array and object comparisons. - Normalized array comparisons to treat undefined/null as empty arrays. - Added deep comparison for objects and improved handling of primitive values. - Enhanced projectIds comparison to ensure consistent MongoDB ObjectId handling. refactor: remove redundant properties from IAgent interface in agent schema chore: update localization for agent detail component and clean up imports ci: update access middleware tests chore: remove unused PermissionTypes import from Role model ci: update AclEntry model tests ci: update button accessibility labels in AgentDetail tests refactor: update exhaustive dep. lint warning
2025-06-13 15:06:36 +02:00
const queryClient = useQueryClient();
// Close dropdown when clicking outside the dropdown menu
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
dropdownOpen &&
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node)
) {
setDropdownOpen(false);
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [dropdownOpen]);
/**
* Navigate to chat with the selected agent
*/
const handleStartChat = () => {
if (agent) {
🔧 fix: Merge and Rebase Conflicts - Move AgentCategory from api/models to @packages/data-schemas structure - Add schema, types, methods, and model following codebase conventions - Implement auto-seeding of default categories during AppService startup - Update marketplace controller to use new data-schemas methods - Remove old model file and standalone seed script refactor: unify agent marketplace to single endpoint with cursor pagination - Replace multiple marketplace routes with unified /marketplace endpoint - Add query string controls: category, search, limit, cursor, promoted, requiredPermission - Implement cursor-based pagination replacing page-based system - Integrate ACL permissions for proper access control - Fix ObjectId constructor error in Agent model - Update React components to use unified useGetMarketplaceAgentsQuery hook - Enhance type safety and remove deprecated useDynamicAgentQuery - Update tests for new marketplace architecture -Known issues: see more button after category switching + Unit tests feat: add icon property to ProcessedAgentCategory interface - Add useMarketplaceAgentsInfiniteQuery and useGetAgentCategoriesQuery to client/src/data-provider/Agents/ - Replace manual pagination in AgentGrid with infinite query pattern - Update imports to use local data provider instead of librechat-data-provider - Add proper permission handling with PERMISSION_BITS.VIEW/EDIT constants - Improve agent access control by adding requiredPermission validation in backend - Remove manual cursor/state management in favor of infinite query built-ins - Maintain existing search and category filtering functionality refactor: consolidate agent marketplace endpoints into main agents API and improve data management consistency - Remove dedicated marketplace controller and routes, merging functionality into main agents v1 API - Add countPromotedAgents function to Agent model for promoted agents count - Enhance getListAgents handler with marketplace filtering (category, search, promoted status) - Move getAgentCategories from marketplace to v1 controller with same functionality - Update agent mutations to invalidate marketplace queries and handle multiple permission levels - Improve cache management by updating all agent query variants (VIEW/EDIT permissions) - Consolidate agent data access patterns for better maintainability and consistency - Remove duplicate marketplace route definitions and middleware selected view only agents injected in the drop down fix: remove minlength validation for support contact name in agent schema feat: add validation and error messages for agent name in AgentConfig and AgentPanel fix: update agent permission check logic in AgentPanel to simplify condition Fix linting WIP Fix Unit tests WIP ESLint fixes eslint fix refactor: enhance isDuplicateVersion function in Agent model for improved comparison logic - Introduced handling for undefined/null values in array and object comparisons. - Normalized array comparisons to treat undefined/null as empty arrays. - Added deep comparison for objects and improved handling of primitive values. - Enhanced projectIds comparison to ensure consistent MongoDB ObjectId handling. refactor: remove redundant properties from IAgent interface in agent schema chore: update localization for agent detail component and clean up imports ci: update access middleware tests chore: remove unused PermissionTypes import from Role model ci: update AclEntry model tests ci: update button accessibility labels in AgentDetail tests refactor: update exhaustive dep. lint warning
2025-06-13 15:06:36 +02:00
const keys = [QueryKeys.agents, { requiredPermission: PERMISSION_BITS.EDIT }];
const listResp = queryClient.getQueryData<AgentListResponse>(keys);
if (listResp != null) {
if (!listResp.data.some((a) => a.id === agent.id)) {
const currentAgents = [agent, ...JSON.parse(JSON.stringify(listResp.data))];
queryClient.setQueryData<AgentListResponse>(keys, { ...listResp, data: currentAgents });
}
}
localStorage.setItem(`${LocalStorageKeys.AGENT_ID_PREFIX}0`, agent.id);
queryClient.setQueryData<t.TMessage[]>(
[QueryKeys.messages, conversation?.conversationId ?? Constants.NEW_CONVO],
[],
);
queryClient.invalidateQueries([QueryKeys.messages]);
newConversation({
template: {
conversationId: Constants.NEW_CONVO as string,
endpoint: EModelEndpoint.agents,
agent_id: agent.id,
title: `Chat with ${agent.name || 'Agent'}`,
},
});
}
};
/**
* Copy the agent's shareable link to clipboard
*/
const handleCopyLink = () => {
const baseUrl = new URL(window.location.origin);
const chatUrl = `${baseUrl.origin}/c/new?agent_id=${agent.id}`;
navigator.clipboard
.writeText(chatUrl)
.then(() => {
showToast({
🔧 fix: Merge and Rebase Conflicts - Move AgentCategory from api/models to @packages/data-schemas structure - Add schema, types, methods, and model following codebase conventions - Implement auto-seeding of default categories during AppService startup - Update marketplace controller to use new data-schemas methods - Remove old model file and standalone seed script refactor: unify agent marketplace to single endpoint with cursor pagination - Replace multiple marketplace routes with unified /marketplace endpoint - Add query string controls: category, search, limit, cursor, promoted, requiredPermission - Implement cursor-based pagination replacing page-based system - Integrate ACL permissions for proper access control - Fix ObjectId constructor error in Agent model - Update React components to use unified useGetMarketplaceAgentsQuery hook - Enhance type safety and remove deprecated useDynamicAgentQuery - Update tests for new marketplace architecture -Known issues: see more button after category switching + Unit tests feat: add icon property to ProcessedAgentCategory interface - Add useMarketplaceAgentsInfiniteQuery and useGetAgentCategoriesQuery to client/src/data-provider/Agents/ - Replace manual pagination in AgentGrid with infinite query pattern - Update imports to use local data provider instead of librechat-data-provider - Add proper permission handling with PERMISSION_BITS.VIEW/EDIT constants - Improve agent access control by adding requiredPermission validation in backend - Remove manual cursor/state management in favor of infinite query built-ins - Maintain existing search and category filtering functionality refactor: consolidate agent marketplace endpoints into main agents API and improve data management consistency - Remove dedicated marketplace controller and routes, merging functionality into main agents v1 API - Add countPromotedAgents function to Agent model for promoted agents count - Enhance getListAgents handler with marketplace filtering (category, search, promoted status) - Move getAgentCategories from marketplace to v1 controller with same functionality - Update agent mutations to invalidate marketplace queries and handle multiple permission levels - Improve cache management by updating all agent query variants (VIEW/EDIT permissions) - Consolidate agent data access patterns for better maintainability and consistency - Remove duplicate marketplace route definitions and middleware selected view only agents injected in the drop down fix: remove minlength validation for support contact name in agent schema feat: add validation and error messages for agent name in AgentConfig and AgentPanel fix: update agent permission check logic in AgentPanel to simplify condition Fix linting WIP Fix Unit tests WIP ESLint fixes eslint fix refactor: enhance isDuplicateVersion function in Agent model for improved comparison logic - Introduced handling for undefined/null values in array and object comparisons. - Normalized array comparisons to treat undefined/null as empty arrays. - Added deep comparison for objects and improved handling of primitive values. - Enhanced projectIds comparison to ensure consistent MongoDB ObjectId handling. refactor: remove redundant properties from IAgent interface in agent schema chore: update localization for agent detail component and clean up imports ci: update access middleware tests chore: remove unused PermissionTypes import from Role model ci: update AclEntry model tests ci: update button accessibility labels in AgentDetail tests refactor: update exhaustive dep. lint warning
2025-06-13 15:06:36 +02:00
message: localize('com_agents_link_copied'),
});
})
.catch(() => {
showToast({
message: localize('com_agents_link_copy_failed'),
});
});
};
/**
* Format contact information with mailto links when appropriate
*/
const formatContact = () => {
if (!agent?.support_contact) return null;
const { name, email } = agent.support_contact;
if (name && email) {
return (
<a href={`mailto:${email}`} className="text-primary hover:underline">
{name}
</a>
);
}
if (email) {
return (
<a href={`mailto:${email}`} className="text-primary hover:underline">
{email}
</a>
);
}
if (name) {
return <span>{name}</span>;
}
return null;
};
return (
<Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
<DialogContent ref={dialogRef} className="max-h-[90vh] overflow-y-auto py-8 sm:max-w-[450px]">
{/* Context menu - top right */}
<div ref={dropdownRef} className="absolute right-12 top-5 z-50">
<Button
variant="ghost"
size="icon"
className="h-8 w-8 rounded-lg text-text-secondary hover:bg-surface-hover hover:text-text-primary dark:hover:bg-surface-hover"
🔧 fix: Merge and Rebase Conflicts - Move AgentCategory from api/models to @packages/data-schemas structure - Add schema, types, methods, and model following codebase conventions - Implement auto-seeding of default categories during AppService startup - Update marketplace controller to use new data-schemas methods - Remove old model file and standalone seed script refactor: unify agent marketplace to single endpoint with cursor pagination - Replace multiple marketplace routes with unified /marketplace endpoint - Add query string controls: category, search, limit, cursor, promoted, requiredPermission - Implement cursor-based pagination replacing page-based system - Integrate ACL permissions for proper access control - Fix ObjectId constructor error in Agent model - Update React components to use unified useGetMarketplaceAgentsQuery hook - Enhance type safety and remove deprecated useDynamicAgentQuery - Update tests for new marketplace architecture -Known issues: see more button after category switching + Unit tests feat: add icon property to ProcessedAgentCategory interface - Add useMarketplaceAgentsInfiniteQuery and useGetAgentCategoriesQuery to client/src/data-provider/Agents/ - Replace manual pagination in AgentGrid with infinite query pattern - Update imports to use local data provider instead of librechat-data-provider - Add proper permission handling with PERMISSION_BITS.VIEW/EDIT constants - Improve agent access control by adding requiredPermission validation in backend - Remove manual cursor/state management in favor of infinite query built-ins - Maintain existing search and category filtering functionality refactor: consolidate agent marketplace endpoints into main agents API and improve data management consistency - Remove dedicated marketplace controller and routes, merging functionality into main agents v1 API - Add countPromotedAgents function to Agent model for promoted agents count - Enhance getListAgents handler with marketplace filtering (category, search, promoted status) - Move getAgentCategories from marketplace to v1 controller with same functionality - Update agent mutations to invalidate marketplace queries and handle multiple permission levels - Improve cache management by updating all agent query variants (VIEW/EDIT permissions) - Consolidate agent data access patterns for better maintainability and consistency - Remove duplicate marketplace route definitions and middleware selected view only agents injected in the drop down fix: remove minlength validation for support contact name in agent schema feat: add validation and error messages for agent name in AgentConfig and AgentPanel fix: update agent permission check logic in AgentPanel to simplify condition Fix linting WIP Fix Unit tests WIP ESLint fixes eslint fix refactor: enhance isDuplicateVersion function in Agent model for improved comparison logic - Introduced handling for undefined/null values in array and object comparisons. - Normalized array comparisons to treat undefined/null as empty arrays. - Added deep comparison for objects and improved handling of primitive values. - Enhanced projectIds comparison to ensure consistent MongoDB ObjectId handling. refactor: remove redundant properties from IAgent interface in agent schema chore: update localization for agent detail component and clean up imports ci: update access middleware tests chore: remove unused PermissionTypes import from Role model ci: update AclEntry model tests ci: update button accessibility labels in AgentDetail tests refactor: update exhaustive dep. lint warning
2025-06-13 15:06:36 +02:00
aria-label={localize('com_agents_more_options')}
aria-expanded={dropdownOpen}
aria-haspopup="menu"
onClick={(e) => {
e.stopPropagation();
setDropdownOpen(!dropdownOpen);
}}
>
<DotsIcon className="h-4 w-4" />
</Button>
{/* Simple dropdown menu */}
{dropdownOpen && (
<div className="absolute right-0 top-10 z-[9999] w-48 rounded-xl border border-border-light bg-surface-primary py-1 shadow-lg dark:bg-surface-secondary dark:shadow-2xl">
<button
onClick={(e) => {
e.stopPropagation();
setDropdownOpen(false);
handleCopyLink();
}}
className="w-full px-3 py-2 text-left text-sm text-text-primary transition-colors hover:bg-surface-hover focus:bg-surface-hover focus:outline-none"
>
{localize('com_agents_copy_link')}
</button>
</div>
)}
</div>
{/* Agent avatar - top center */}
<div className="mt-6 flex justify-center">{renderAgentAvatar(agent, { size: 'xl' })}</div>
{/* Agent name - center aligned below image */}
<div className="mt-3 text-center">
<h2 className="text-2xl font-bold text-gray-900 dark:text-white">
{agent?.name || localize('com_agents_loading')}
</h2>
</div>
{/* Contact info - center aligned below name */}
{agent?.support_contact && formatContact() && (
<div className="mt-1 text-center text-sm text-gray-600 dark:text-gray-400">
{localize('com_agents_contact')}: {formatContact()}
</div>
)}
{/* Agent description - below contact */}
<div className="mt-4 whitespace-pre-wrap px-6 text-center text-base text-gray-700 dark:text-gray-300">
{agent?.description || (
<span className="italic text-gray-400">{localize('com_agents_no_description')}</span>
)}
</div>
{/* Action button */}
<div className="mb-4 mt-6 flex justify-center">
<Button className="w-full max-w-xs" onClick={handleStartChat} disabled={!agent}>
{localize('com_agents_start_chat')}
</Button>
</div>
</DialogContent>
</Dialog>
);
};
export default AgentDetail;