From 93a628d7a2c2ba07b1c92a118a7d0774da9d706e Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Sun, 15 Mar 2026 10:35:44 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=8E=20fix:=20Respect=20fileConfig.disa?= =?UTF-8?q?bled=20for=20Agents=20Endpoint=20Upload=20Button=20(#12238)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: respect fileConfig.disabled for agents endpoint upload button The isAgents check was OR'd without the !isUploadDisabled guard, bypassing the fileConfig.endpoints.agents.disabled setting and always rendering the attach file menu for agents. * test: add regression tests for fileConfig.disabled upload guard Cover the isUploadDisabled rendering gate for agents and assistants endpoints, preventing silent reintroduction of the bypass bug. * test: cover disabled fallback chain in useAgentFileConfig Verify agents-disabled propagates when no provider is set, when provider has no specific config (agents as fallback), and that provider-specific enabled overrides agents disabled. --- .../Chat/Input/Files/AttachFileChat.tsx | 2 +- .../Files/__tests__/AttachFileChat.spec.tsx | 59 ++++++++++++++++++- .../Agents/__tests__/AgentFileConfig.spec.tsx | 47 ++++++++++++++- 3 files changed, 103 insertions(+), 5 deletions(-) diff --git a/client/src/components/Chat/Input/Files/AttachFileChat.tsx b/client/src/components/Chat/Input/Files/AttachFileChat.tsx index 00a0b7aaa8..2f954d01d5 100644 --- a/client/src/components/Chat/Input/Files/AttachFileChat.tsx +++ b/client/src/components/Chat/Input/Files/AttachFileChat.tsx @@ -91,7 +91,7 @@ function AttachFileChat({ if (isAssistants && endpointSupportsFiles && !isUploadDisabled) { return ; - } else if (isAgents || (endpointSupportsFiles && !isUploadDisabled)) { + } else if ((isAgents || endpointSupportsFiles) && !isUploadDisabled) { return ( > = {}; let mockAgentQueryData: Partial | undefined; @@ -65,6 +67,7 @@ function renderComponent(conversation: Record | null, disableIn describe('AttachFileChat', () => { beforeEach(() => { + mockFileConfig = defaultFileConfig; mockAgentsMap = {}; mockAgentQueryData = undefined; mockAttachFileMenuProps = {}; @@ -148,6 +151,60 @@ describe('AttachFileChat', () => { }); }); + describe('upload disabled rendering', () => { + it('renders null for agents endpoint when fileConfig.agents.disabled is true', () => { + mockFileConfig = mergeFileConfig({ + endpoints: { + [EModelEndpoint.agents]: { disabled: true }, + }, + }); + const { container } = renderComponent({ + endpoint: EModelEndpoint.agents, + agent_id: 'agent-1', + }); + expect(container.innerHTML).toBe(''); + }); + + it('renders null for agents endpoint when disableInputs is true', () => { + const { container } = renderComponent( + { endpoint: EModelEndpoint.agents, agent_id: 'agent-1' }, + true, + ); + expect(container.innerHTML).toBe(''); + }); + + it('renders AttachFile for assistants endpoint when not disabled', () => { + renderComponent({ endpoint: EModelEndpoint.assistants }); + expect(screen.getByTestId('attach-file')).toBeInTheDocument(); + }); + + it('renders AttachFileMenu when provider-specific config overrides agents disabled', () => { + mockFileConfig = mergeFileConfig({ + endpoints: { + Moonshot: { disabled: false, fileLimit: 5 }, + [EModelEndpoint.agents]: { disabled: true }, + }, + }); + mockAgentsMap = { + 'agent-1': { provider: 'Moonshot', model_parameters: {} } as Partial, + }; + renderComponent({ endpoint: EModelEndpoint.agents, agent_id: 'agent-1' }); + expect(screen.getByTestId('attach-file-menu')).toBeInTheDocument(); + }); + + it('renders null for assistants endpoint when fileConfig.assistants.disabled is true', () => { + mockFileConfig = mergeFileConfig({ + endpoints: { + [EModelEndpoint.assistants]: { disabled: true }, + }, + }); + const { container } = renderComponent({ + endpoint: EModelEndpoint.assistants, + }); + expect(container.innerHTML).toBe(''); + }); + }); + describe('endpointFileConfig resolution', () => { it('passes Moonshot-specific file config for agent with Moonshot provider', () => { mockAgentsMap = { diff --git a/client/src/components/SidePanel/Agents/__tests__/AgentFileConfig.spec.tsx b/client/src/components/SidePanel/Agents/__tests__/AgentFileConfig.spec.tsx index aeb0dd3ff9..2bbd3fea22 100644 --- a/client/src/components/SidePanel/Agents/__tests__/AgentFileConfig.spec.tsx +++ b/client/src/components/SidePanel/Agents/__tests__/AgentFileConfig.spec.tsx @@ -18,7 +18,7 @@ const mockEndpointsConfig: TEndpointsConfig = { 'Some Endpoint': { type: EModelEndpoint.custom, userProvide: false, order: 9999 }, }; -let mockFileConfig = mergeFileConfig({ +const defaultFileConfig = mergeFileConfig({ endpoints: { Moonshot: { fileLimit: 5 }, [EModelEndpoint.agents]: { fileLimit: 20 }, @@ -26,6 +26,8 @@ let mockFileConfig = mergeFileConfig({ }, }); +let mockFileConfig = defaultFileConfig; + jest.mock('~/data-provider', () => ({ useGetEndpointsQuery: () => ({ data: mockEndpointsConfig }), useGetFileConfig: ({ select }: { select?: (data: unknown) => unknown }) => ({ @@ -118,13 +120,16 @@ describe('AgentPanel file config resolution (useAgentFileConfig)', () => { }); describe('disabled state', () => { + beforeEach(() => { + mockFileConfig = defaultFileConfig; + }); + it('reports not disabled for standard config', () => { render(); expect(screen.getByTestId('disabled').textContent).toBe('false'); }); it('reports disabled when provider-specific config is disabled', () => { - const original = mockFileConfig; mockFileConfig = mergeFileConfig({ endpoints: { Moonshot: { disabled: true }, @@ -135,8 +140,44 @@ describe('AgentPanel file config resolution (useAgentFileConfig)', () => { render(); expect(screen.getByTestId('disabled').textContent).toBe('true'); + }); - mockFileConfig = original; + it('reports disabled when agents config is disabled and no provider set', () => { + mockFileConfig = mergeFileConfig({ + endpoints: { + [EModelEndpoint.agents]: { disabled: true }, + default: { fileLimit: 10 }, + }, + }); + + render(); + expect(screen.getByTestId('disabled').textContent).toBe('true'); + }); + + it('reports disabled when agents is disabled and provider has no specific config', () => { + mockFileConfig = mergeFileConfig({ + endpoints: { + [EModelEndpoint.agents]: { disabled: true }, + default: { fileLimit: 10 }, + }, + }); + + render(); + expect(screen.getByTestId('disabled').textContent).toBe('true'); + }); + + it('provider-specific enabled overrides agents disabled', () => { + mockFileConfig = mergeFileConfig({ + endpoints: { + Moonshot: { disabled: false, fileLimit: 5 }, + [EModelEndpoint.agents]: { disabled: true }, + default: { fileLimit: 10 }, + }, + }); + + render(); + expect(screen.getByTestId('disabled').textContent).toBe('false'); + expect(screen.getByTestId('fileLimit').textContent).toBe('5'); }); });