🔧 fix: Agent Resource Form, Convo Menu Style, Ensure Draft Clears on Submission (#6925)

*  style: Adjust z-index for popover UI and update className in ConvoOptions

*  feat: Add 'spec' field to conversation query selection

* 🛠️ fix: add back conversationId to use Constants.PENDING_CONVO in useSSE hook on submission to allow text drafts to clear

*  chore: add .clineignore to .gitignore for Cline configuration

*  refactor: memoize FileSearchCheckbox component for performance optimization

* fix: agent resource management by adding tool_resource to agent's tools if missing
This commit is contained in:
Danny Avila 2025-04-16 18:14:34 -04:00 committed by GitHub
parent 6edd93f99e
commit 851938e7a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 69 additions and 8 deletions

3
.gitignore vendored
View file

@ -52,6 +52,9 @@ bower_components/
*.d.ts
!vite-env.d.ts
# Cline
.clineignore
# Floobits
.floo
.floobit

View file

@ -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) {

View file

@ -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());

View file

@ -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)

View file

@ -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 && (
<ShareButton

View file

@ -1,3 +1,4 @@
import { memo } from 'react';
import { AgentCapabilities } from 'librechat-data-provider';
import { useFormContext, Controller } from 'react-hook-form';
import type { AgentForm } from '~/common';
@ -12,7 +13,7 @@ import { CircleHelpIcon } from '~/components/svg';
import { useLocalize } from '~/hooks';
import { ESide } from '~/common';
export default function FileSearchCheckbox() {
function FileSearchCheckbox() {
const localize = useLocalize();
const methods = useFormContext<AgentForm>();
const { control, setValue, getValues } = methods;
@ -67,3 +68,5 @@ export default function FileSearchCheckbox() {
</>
);
}
export default memo(FileSearchCheckbox);

View file

@ -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,

View file

@ -128,7 +128,7 @@ export default function useSSE(
return {
...prev,
title,
conversationId: prev?.conversationId,
conversationId: Constants.PENDING_CONVO as string,
};
});
let { payload } = payloadData;

View file

@ -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;