LibreChat/client/src/Providers/AgentPanelContext.tsx
Danny Avila 33b4a97b42
🔒 fix: Agents Config/Permission Checks after Streamline Change (#8089)
* refactor: access control logic to TypeScript

* chore: Change EndpointURLs to a constant object for improved type safety

* 🐛 fix: Enhance agent access control by adding skipAgentCheck functionality

* 🐛 fix: Add endpointFileConfig prop to AttachFileMenu and update file handling logic

* 🐛 fix: Update tool handling logic to support optional groupedTools and improve null checks, add dedicated tool dialog for Assistants

* chore: Export Accordion component from UI index for improved modularity

* feat: Add ActivePanelContext for managing active panel state across components

* chore: Replace string IDs with EModelEndpoint constants for assistants and agents in useSideNavLinks

* fix: Integrate access checks for agent creation and deletion routes in actions.js
2025-06-26 18:53:05 -04:00

96 lines
3.1 KiB
TypeScript

import React, { createContext, useContext, useState } from 'react';
import { Constants, EModelEndpoint } from 'librechat-data-provider';
import type { TPlugin, AgentToolType, Action, MCP } from 'librechat-data-provider';
import type { AgentPanelContextType } from '~/common';
import { useAvailableToolsQuery, useGetActionsQuery } from '~/data-provider';
import { useLocalize } from '~/hooks';
import { Panel } from '~/common';
const AgentPanelContext = createContext<AgentPanelContextType | undefined>(undefined);
export function useAgentPanelContext() {
const context = useContext(AgentPanelContext);
if (context === undefined) {
throw new Error('useAgentPanelContext must be used within an AgentPanelProvider');
}
return context;
}
/** Houses relevant state for the Agent Form Panels (formerly 'commonProps') */
export function AgentPanelProvider({ children }: { children: React.ReactNode }) {
const localize = useLocalize();
const [mcp, setMcp] = useState<MCP | undefined>(undefined);
const [mcps, setMcps] = useState<MCP[] | undefined>(undefined);
const [action, setAction] = useState<Action | undefined>(undefined);
const [activePanel, setActivePanel] = useState<Panel>(Panel.builder);
const [agent_id, setCurrentAgentId] = useState<string | undefined>(undefined);
const { data: actions } = useGetActionsQuery(EModelEndpoint.agents, {
enabled: !!agent_id,
});
const { data: pluginTools } = useAvailableToolsQuery(EModelEndpoint.agents, {
enabled: !!agent_id,
});
const tools =
pluginTools?.map((tool) => ({
tool_id: tool.pluginKey,
metadata: tool as TPlugin,
agent_id: agent_id || '',
})) || [];
const groupedTools = tools?.reduce(
(acc, tool) => {
if (tool.tool_id.includes(Constants.mcp_delimiter)) {
const [_toolName, serverName] = tool.tool_id.split(Constants.mcp_delimiter);
const groupKey = `${serverName.toLowerCase()}`;
if (!acc[groupKey]) {
acc[groupKey] = {
tool_id: groupKey,
metadata: {
name: `${serverName}`,
pluginKey: groupKey,
description: `${localize('com_ui_tool_collection_prefix')} ${serverName}`,
icon: tool.metadata.icon || '',
} as TPlugin,
agent_id: agent_id || '',
tools: [],
};
}
acc[groupKey].tools?.push({
tool_id: tool.tool_id,
metadata: tool.metadata,
agent_id: agent_id || '',
});
} else {
acc[tool.tool_id] = {
tool_id: tool.tool_id,
metadata: tool.metadata,
agent_id: agent_id || '',
};
}
return acc;
},
{} as Record<string, AgentToolType & { tools?: AgentToolType[] }>,
);
const value = {
action,
setAction,
mcp,
setMcp,
mcps,
setMcps,
activePanel,
setActivePanel,
setCurrentAgentId,
agent_id,
groupedTools,
/** Query data for actions and tools */
actions,
tools,
};
return <AgentPanelContext.Provider value={value}>{children}</AgentPanelContext.Provider>;
}