Skip to content

Commit 851938e

Browse files
authored
🔧 fix: Agent Resource Form, Convo Menu Style, Ensure Draft Clears on Submission (danny-avila#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
1 parent 6edd93f commit 851938e

File tree

9 files changed

+69
-8
lines changed

9 files changed

+69
-8
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ bower_components/
5252
*.d.ts
5353
!vite-env.d.ts
5454

55+
# Cline
56+
.clineignore
57+
5558
# Floobits
5659
.floo
5760
.floobit

api/models/Agent.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,11 @@ const updateAgent = async (searchParameter, updateData) => {
153153
*/
154154
const addAgentResourceFile = async ({ agent_id, tool_resource, file_id }) => {
155155
const searchParameter = { id: agent_id };
156-
156+
let agent = await getAgent(searchParameter);
157+
if (!agent) {
158+
throw new Error('Agent not found for adding resource file');
159+
}
157160
const fileIdsPath = `tool_resources.${tool_resource}.file_ids`;
158-
159161
await Agent.updateOne(
160162
{
161163
id: agent_id,
@@ -168,7 +170,12 @@ const addAgentResourceFile = async ({ agent_id, tool_resource, file_id }) => {
168170
},
169171
);
170172

171-
const updateData = { $addToSet: { [fileIdsPath]: file_id } };
173+
const updateData = {
174+
$addToSet: {
175+
tools: tool_resource,
176+
[fileIdsPath]: file_id,
177+
},
178+
};
172179

173180
const updatedAgent = await updateAgent(searchParameter, updateData);
174181
if (updatedAgent) {

api/models/Agent.spec.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,50 @@ describe('Agent Resource File Operations', () => {
3333
return agent;
3434
};
3535

36+
test('should add tool_resource to tools if missing', async () => {
37+
const agent = await createBasicAgent();
38+
const fileId = uuidv4();
39+
const toolResource = 'file_search';
40+
41+
const updatedAgent = await addAgentResourceFile({
42+
agent_id: agent.id,
43+
tool_resource: toolResource,
44+
file_id: fileId,
45+
});
46+
47+
expect(updatedAgent.tools).toContain(toolResource);
48+
expect(Array.isArray(updatedAgent.tools)).toBe(true);
49+
// Should not duplicate
50+
const count = updatedAgent.tools.filter((t) => t === toolResource).length;
51+
expect(count).toBe(1);
52+
});
53+
54+
test('should not duplicate tool_resource in tools if already present', async () => {
55+
const agent = await createBasicAgent();
56+
const fileId1 = uuidv4();
57+
const fileId2 = uuidv4();
58+
const toolResource = 'file_search';
59+
60+
// First add
61+
await addAgentResourceFile({
62+
agent_id: agent.id,
63+
tool_resource: toolResource,
64+
file_id: fileId1,
65+
});
66+
67+
// Second add (should not duplicate)
68+
const updatedAgent = await addAgentResourceFile({
69+
agent_id: agent.id,
70+
tool_resource: toolResource,
71+
file_id: fileId2,
72+
});
73+
74+
expect(updatedAgent.tools).toContain(toolResource);
75+
expect(Array.isArray(updatedAgent.tools)).toBe(true);
76+
const count = updatedAgent.tools.filter((t) => t === toolResource).length;
77+
expect(count).toBe(1);
78+
});
79+
3680
test('should handle concurrent file additions', async () => {
3781
const agent = await createBasicAgent();
3882
const fileIds = Array.from({ length: 10 }, () => uuidv4());

api/models/Conversation.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ module.exports = {
193193
try {
194194
const convos = await Conversation.find(query)
195195
.select(
196-
'conversationId endpoint title createdAt updatedAt user model agent_id assistant_id',
196+
'conversationId endpoint title createdAt updatedAt user model agent_id assistant_id spec',
197197
)
198198
.sort({ updatedAt: order === 'asc' ? 1 : -1 })
199199
.limit(limit + 1)

client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ function ConvoOptions({
202202
id={`conversation-menu-${conversationId}`}
203203
aria-label={localize('com_nav_convo_menu_options')}
204204
className={cn(
205-
'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',
205+
'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',
206206
isActiveConvo === true || isPopoverActive
207207
? 'opacity-100'
208208
: 'opacity-0 focus:opacity-100 group-focus-within:opacity-100 group-hover:opacity-100 data-[open]:opacity-100',
@@ -221,6 +221,7 @@ function ConvoOptions({
221221
}
222222
items={dropdownItems}
223223
menuId={menuId}
224+
className="z-30"
224225
/>
225226
{showShareDialog && (
226227
<ShareButton

client/src/components/SidePanel/Agents/FileSearchCheckbox.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { memo } from 'react';
12
import { AgentCapabilities } from 'librechat-data-provider';
23
import { useFormContext, Controller } from 'react-hook-form';
34
import type { AgentForm } from '~/common';
@@ -12,7 +13,7 @@ import { CircleHelpIcon } from '~/components/svg';
1213
import { useLocalize } from '~/hooks';
1314
import { ESide } from '~/common';
1415

15-
export default function FileSearchCheckbox() {
16+
function FileSearchCheckbox() {
1617
const localize = useLocalize();
1718
const methods = useFormContext<AgentForm>();
1819
const { control, setValue, getValues } = methods;
@@ -67,3 +68,5 @@ export default function FileSearchCheckbox() {
6768
</>
6869
);
6970
}
71+
72+
export default memo(FileSearchCheckbox);

client/src/data-provider/Files/mutations.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ export const useUploadFileMutation = (
7676
...prevResources,
7777
[tool_resource]: prevResource,
7878
};
79+
if (!agent.tools?.includes(tool_resource)) {
80+
update['tools'] = [...(agent.tools ?? []), tool_resource];
81+
}
7982
return {
8083
...agent,
8184
...update,

client/src/hooks/SSE/useSSE.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export default function useSSE(
128128
return {
129129
...prev,
130130
title,
131-
conversationId: prev?.conversationId,
131+
conversationId: Constants.PENDING_CONVO as string,
132132
};
133133
});
134134
let { payload } = payloadData;

client/src/style.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2509,7 +2509,7 @@ html {
25092509
}
25102510

25112511
.popover-ui {
2512-
z-index: 1000;
2512+
/* z-index: 1000; */
25132513
display: flex;
25142514
max-height: min(var(--popover-available-height, 1700px), 1700px);
25152515
flex-direction: column;

0 commit comments

Comments
 (0)