mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-16 16:30:15 +01:00
🔧 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:
parent
6edd93f99e
commit
851938e7a6
9 changed files with 69 additions and 8 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -52,6 +52,9 @@ bower_components/
|
||||||
*.d.ts
|
*.d.ts
|
||||||
!vite-env.d.ts
|
!vite-env.d.ts
|
||||||
|
|
||||||
|
# Cline
|
||||||
|
.clineignore
|
||||||
|
|
||||||
# Floobits
|
# Floobits
|
||||||
.floo
|
.floo
|
||||||
.floobit
|
.floobit
|
||||||
|
|
|
||||||
|
|
@ -153,9 +153,11 @@ const updateAgent = async (searchParameter, updateData) => {
|
||||||
*/
|
*/
|
||||||
const addAgentResourceFile = async ({ agent_id, tool_resource, file_id }) => {
|
const addAgentResourceFile = async ({ agent_id, tool_resource, file_id }) => {
|
||||||
const searchParameter = { id: agent_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`;
|
const fileIdsPath = `tool_resources.${tool_resource}.file_ids`;
|
||||||
|
|
||||||
await Agent.updateOne(
|
await Agent.updateOne(
|
||||||
{
|
{
|
||||||
id: agent_id,
|
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);
|
const updatedAgent = await updateAgent(searchParameter, updateData);
|
||||||
if (updatedAgent) {
|
if (updatedAgent) {
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,50 @@ describe('Agent Resource File Operations', () => {
|
||||||
return agent;
|
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 () => {
|
test('should handle concurrent file additions', async () => {
|
||||||
const agent = await createBasicAgent();
|
const agent = await createBasicAgent();
|
||||||
const fileIds = Array.from({ length: 10 }, () => uuidv4());
|
const fileIds = Array.from({ length: 10 }, () => uuidv4());
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,7 @@ module.exports = {
|
||||||
try {
|
try {
|
||||||
const convos = await Conversation.find(query)
|
const convos = await Conversation.find(query)
|
||||||
.select(
|
.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 })
|
.sort({ updatedAt: order === 'asc' ? 1 : -1 })
|
||||||
.limit(limit + 1)
|
.limit(limit + 1)
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,7 @@ function ConvoOptions({
|
||||||
id={`conversation-menu-${conversationId}`}
|
id={`conversation-menu-${conversationId}`}
|
||||||
aria-label={localize('com_nav_convo_menu_options')}
|
aria-label={localize('com_nav_convo_menu_options')}
|
||||||
className={cn(
|
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
|
isActiveConvo === true || isPopoverActive
|
||||||
? 'opacity-100'
|
? 'opacity-100'
|
||||||
: 'opacity-0 focus:opacity-100 group-focus-within:opacity-100 group-hover:opacity-100 data-[open]: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}
|
items={dropdownItems}
|
||||||
menuId={menuId}
|
menuId={menuId}
|
||||||
|
className="z-30"
|
||||||
/>
|
/>
|
||||||
{showShareDialog && (
|
{showShareDialog && (
|
||||||
<ShareButton
|
<ShareButton
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { memo } from 'react';
|
||||||
import { AgentCapabilities } from 'librechat-data-provider';
|
import { AgentCapabilities } from 'librechat-data-provider';
|
||||||
import { useFormContext, Controller } from 'react-hook-form';
|
import { useFormContext, Controller } from 'react-hook-form';
|
||||||
import type { AgentForm } from '~/common';
|
import type { AgentForm } from '~/common';
|
||||||
|
|
@ -12,7 +13,7 @@ import { CircleHelpIcon } from '~/components/svg';
|
||||||
import { useLocalize } from '~/hooks';
|
import { useLocalize } from '~/hooks';
|
||||||
import { ESide } from '~/common';
|
import { ESide } from '~/common';
|
||||||
|
|
||||||
export default function FileSearchCheckbox() {
|
function FileSearchCheckbox() {
|
||||||
const localize = useLocalize();
|
const localize = useLocalize();
|
||||||
const methods = useFormContext<AgentForm>();
|
const methods = useFormContext<AgentForm>();
|
||||||
const { control, setValue, getValues } = methods;
|
const { control, setValue, getValues } = methods;
|
||||||
|
|
@ -67,3 +68,5 @@ export default function FileSearchCheckbox() {
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default memo(FileSearchCheckbox);
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,9 @@ export const useUploadFileMutation = (
|
||||||
...prevResources,
|
...prevResources,
|
||||||
[tool_resource]: prevResource,
|
[tool_resource]: prevResource,
|
||||||
};
|
};
|
||||||
|
if (!agent.tools?.includes(tool_resource)) {
|
||||||
|
update['tools'] = [...(agent.tools ?? []), tool_resource];
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
...agent,
|
...agent,
|
||||||
...update,
|
...update,
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ export default function useSSE(
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
title,
|
title,
|
||||||
conversationId: prev?.conversationId,
|
conversationId: Constants.PENDING_CONVO as string,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
let { payload } = payloadData;
|
let { payload } = payloadData;
|
||||||
|
|
|
||||||
|
|
@ -2509,7 +2509,7 @@ html {
|
||||||
}
|
}
|
||||||
|
|
||||||
.popover-ui {
|
.popover-ui {
|
||||||
z-index: 1000;
|
/* z-index: 1000; */
|
||||||
display: flex;
|
display: flex;
|
||||||
max-height: min(var(--popover-available-height, 1700px), 1700px);
|
max-height: min(var(--popover-available-height, 1700px), 1700px);
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue