diff --git a/.gitignore b/.gitignore index bd3b596c8..a4d2d8fc7 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,9 @@ bower_components/ *.d.ts !vite-env.d.ts +# Cline +.clineignore + # Floobits .floo .floobit diff --git a/api/models/Agent.js b/api/models/Agent.js index dba0c40ee..0e4321df9 100644 --- a/api/models/Agent.js +++ b/api/models/Agent.js @@ -153,9 +153,11 @@ const updateAgent = async (searchParameter, updateData) => { */ const addAgentResourceFile = async ({ agent_id, tool_resource, file_id }) => { const searchParameter = { id: agent_id }; - + let agent = await getAgent(searchParameter); + if (!agent) { + throw new Error('Agent not found for adding resource file'); + } const fileIdsPath = `tool_resources.${tool_resource}.file_ids`; - await Agent.updateOne( { id: agent_id, @@ -168,7 +170,12 @@ const addAgentResourceFile = async ({ agent_id, tool_resource, file_id }) => { }, ); - const updateData = { $addToSet: { [fileIdsPath]: file_id } }; + const updateData = { + $addToSet: { + tools: tool_resource, + [fileIdsPath]: file_id, + }, + }; const updatedAgent = await updateAgent(searchParameter, updateData); if (updatedAgent) { diff --git a/api/models/Agent.spec.js b/api/models/Agent.spec.js index 0e6d1831f..051cb6800 100644 --- a/api/models/Agent.spec.js +++ b/api/models/Agent.spec.js @@ -33,6 +33,50 @@ describe('Agent Resource File Operations', () => { return agent; }; + test('should add tool_resource to tools if missing', async () => { + const agent = await createBasicAgent(); + const fileId = uuidv4(); + const toolResource = 'file_search'; + + const updatedAgent = await addAgentResourceFile({ + agent_id: agent.id, + tool_resource: toolResource, + file_id: fileId, + }); + + expect(updatedAgent.tools).toContain(toolResource); + expect(Array.isArray(updatedAgent.tools)).toBe(true); + // Should not duplicate + const count = updatedAgent.tools.filter((t) => t === toolResource).length; + expect(count).toBe(1); + }); + + test('should not duplicate tool_resource in tools if already present', async () => { + const agent = await createBasicAgent(); + const fileId1 = uuidv4(); + const fileId2 = uuidv4(); + const toolResource = 'file_search'; + + // First add + await addAgentResourceFile({ + agent_id: agent.id, + tool_resource: toolResource, + file_id: fileId1, + }); + + // Second add (should not duplicate) + const updatedAgent = await addAgentResourceFile({ + agent_id: agent.id, + tool_resource: toolResource, + file_id: fileId2, + }); + + expect(updatedAgent.tools).toContain(toolResource); + expect(Array.isArray(updatedAgent.tools)).toBe(true); + const count = updatedAgent.tools.filter((t) => t === toolResource).length; + expect(count).toBe(1); + }); + test('should handle concurrent file additions', async () => { const agent = await createBasicAgent(); const fileIds = Array.from({ length: 10 }, () => uuidv4()); diff --git a/api/models/Conversation.js b/api/models/Conversation.js index 73841fa9b..50b826c0d 100644 --- a/api/models/Conversation.js +++ b/api/models/Conversation.js @@ -193,7 +193,7 @@ module.exports = { try { const convos = await Conversation.find(query) .select( - 'conversationId endpoint title createdAt updatedAt user model agent_id assistant_id', + 'conversationId endpoint title createdAt updatedAt user model agent_id assistant_id spec', ) .sort({ updatedAt: order === 'asc' ? 1 : -1 }) .limit(limit + 1) diff --git a/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx b/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx index 94f99f62d..1fd74dee3 100644 --- a/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx +++ b/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx @@ -202,7 +202,7 @@ function ConvoOptions({ id={`conversation-menu-${conversationId}`} aria-label={localize('com_nav_convo_menu_options')} className={cn( - 'z-30 inline-flex h-7 w-7 items-center justify-center gap-2 rounded-md border-none p-0 text-sm font-medium ring-ring-primary transition-all duration-200 ease-in-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:opacity-50', + 'inline-flex h-7 w-7 items-center justify-center gap-2 rounded-md border-none p-0 text-sm font-medium ring-ring-primary transition-all duration-200 ease-in-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:opacity-50', isActiveConvo === true || isPopoverActive ? 'opacity-100' : 'opacity-0 focus:opacity-100 group-focus-within:opacity-100 group-hover:opacity-100 data-[open]:opacity-100', @@ -221,6 +221,7 @@ function ConvoOptions({ } items={dropdownItems} menuId={menuId} + className="z-30" /> {showShareDialog && ( (); const { control, setValue, getValues } = methods; @@ -67,3 +68,5 @@ export default function FileSearchCheckbox() { ); } + +export default memo(FileSearchCheckbox); diff --git a/client/src/data-provider/Files/mutations.ts b/client/src/data-provider/Files/mutations.ts index 8ac2a5e49..539eb953e 100644 --- a/client/src/data-provider/Files/mutations.ts +++ b/client/src/data-provider/Files/mutations.ts @@ -76,6 +76,9 @@ export const useUploadFileMutation = ( ...prevResources, [tool_resource]: prevResource, }; + if (!agent.tools?.includes(tool_resource)) { + update['tools'] = [...(agent.tools ?? []), tool_resource]; + } return { ...agent, ...update, diff --git a/client/src/hooks/SSE/useSSE.ts b/client/src/hooks/SSE/useSSE.ts index 2e66bfdef..404247941 100644 --- a/client/src/hooks/SSE/useSSE.ts +++ b/client/src/hooks/SSE/useSSE.ts @@ -128,7 +128,7 @@ export default function useSSE( return { ...prev, title, - conversationId: prev?.conversationId, + conversationId: Constants.PENDING_CONVO as string, }; }); let { payload } = payloadData; diff --git a/client/src/style.css b/client/src/style.css index 201ada00d..3607d3808 100644 --- a/client/src/style.css +++ b/client/src/style.css @@ -2509,7 +2509,7 @@ html { } .popover-ui { - z-index: 1000; + /* z-index: 1000; */ display: flex; max-height: min(var(--popover-available-height, 1700px), 1700px); flex-direction: column;