Skip to content

Commit 01e9b19

Browse files
authored
🤖 feat: Streamline Endpoints to Agent Framework (#8013)
* refactor(buildEndpointOption): Improve error logging in middleware, consolidate `isAgents` builder logic, remove adding `modelsConfig` to `endpointOption` * refactor: parameter extraction and organization in agent services, minimize redundancy of shared fields across objects, make clear distinction of parameters processed uniquely by LibreChat vs LLM Provider Configs * refactor(createPayload): streamline all endpoints to agent route * fix: add `modelLabel` to response sender options for agent initialization * chore: correct log message context in EditController abort controller cleanup * chore: remove unused abortRequest hook * chore: remove unused addToCache module and its dependencies * refactor: remove AskController and related routes, update endpoint URLs (now all streamlined to agents route) * chore: remove unused bedrock route and its related imports * refactor: simplify response sender logic for Google endpoint * chore: add `modelDisplayLabel` handling for agents endpoint * feat: add file search capability to ephemeral agents, update code interpreter selection based of file upload, consolidate main upload menu for all endpoints * feat: implement useToolToggle hook for managing tool toggle state, refactor CodeInterpreter and WebSearch components to utilize new hook * feat: add ToolsDropdown component to BadgeRow for enhanced tool options * feat: introduce BadgeRowContext and BadgeRowProvider for managing conversation state, refactor related components to utilize context * feat: implement useMCPSelect hook for managing MCP selection state, refactor MCPSelect component to utilize new hook * feat: enhance BadgeRowContext with MCPSelect and tool toggle functionality, refactor related components to utilize updated context and hooks * refactor: streamline useToolToggle hook by integrating setEphemeralAgent directly into toggle logic and removing redundant setValue function * refactor: consolidate codeApiKeyForm and searchApiKeyForm from CodeInterpreter and WebSearch to utilize new context properties * refactor: update CheckboxButton to support controlled state and enhance ToolsDropdown with permission-based toggles for web search and code interpreter * refactor: conditionally render CheckboxButton in CodeInterpreter and WebSearch components for improved UI responsiveness * chore: add jotai dependency to package.json and package-lock.json * chore: update brace-expansion package to version 2.0.2 in package-lock.json due to CVE-2025-5889 * Revert "chore: add jotai dependency to package.json and package-lock.json" This reverts commit 69b6997. * refactor: add pinning functionality to CodeInterpreter and WebSearch components, and enhance ToolsDropdown with pin toggle for web search and code interpreter * chore: move MCPIcon to correct location, remove duplicate * fix: update MCP import to use type-only import from librechat-data-provider * feat: implement MCPSubMenu component and integrate pinning functionality into ToolsDropdown * fix: cycling to submenu by using parent menu context * feat: add FileSearch component and integrate it into BadgeRow and ToolsDropdown * chore: import order * chore: remove agent specific logic that would block functionality for streamlined endpoints * chore: linting for `createContextHandlers` * chore: ensure ToolsDropdown doesn't show up for agents * chore: ensure tool resource is selected when dragged to UI * chore: update file search behavior to simulate legacy functionality * feat: ToolDialogs with multiple trigger references, add settings to tool dropdown * refactor: simplify web search and code interpreter settings checks * chore: simplify local storage key for pinned state in useToolToggle * refactor: reinstate agent check in AttachFileChat component, as individual providers will ahve different file configurations * ci: increase timeout for MongoDB connection in Agent tests
1 parent d835f48 commit 01e9b19

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+1468
-1433
lines changed

api/app/clients/BaseClient.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,8 @@ class BaseClient {
792792

793793
userMessage.tokenCount = userMessageTokenCount;
794794
/*
795-
Note: `AskController` saves the user message, so we update the count of its `userMessage` reference
795+
Note: `AgentController` saves the user message if not saved here
796+
(noted by `savedMessageIds`), so we update the count of its `userMessage` reference
796797
*/
797798
if (typeof opts?.getReqData === 'function') {
798799
opts.getReqData({
@@ -801,7 +802,8 @@ class BaseClient {
801802
}
802803
/*
803804
Note: we update the user message to be sure it gets the calculated token count;
804-
though `AskController` saves the user message, EditController does not
805+
though `AgentController` saves the user message if not saved here
806+
(noted by `savedMessageIds`), EditController does not
805807
*/
806808
await userMessagePromise;
807809
await this.updateMessageInDatabase({

api/app/clients/prompts/createContextHandlers.js

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -96,35 +96,35 @@ function createContextHandlers(req, userMessageContent) {
9696
resolvedQueries.length === 0
9797
? '\n\tThe semantic search did not return any results.'
9898
: resolvedQueries
99-
.map((queryResult, index) => {
100-
const file = processedFiles[index];
101-
let contextItems = queryResult.data;
99+
.map((queryResult, index) => {
100+
const file = processedFiles[index];
101+
let contextItems = queryResult.data;
102102

103-
const generateContext = (currentContext) =>
104-
`
103+
const generateContext = (currentContext) =>
104+
`
105105
<file>
106106
<filename>${file.filename}</filename>
107107
<context>${currentContext}
108108
</context>
109109
</file>`;
110110

111-
if (useFullContext) {
112-
return generateContext(`\n${contextItems}`);
113-
}
111+
if (useFullContext) {
112+
return generateContext(`\n${contextItems}`);
113+
}
114114

115-
contextItems = queryResult.data
116-
.map((item) => {
117-
const pageContent = item[0].page_content;
118-
return `
115+
contextItems = queryResult.data
116+
.map((item) => {
117+
const pageContent = item[0].page_content;
118+
return `
119119
<contextItem>
120120
<![CDATA[${pageContent?.trim()}]]>
121121
</contextItem>`;
122-
})
123-
.join('');
122+
})
123+
.join('');
124124

125-
return generateContext(contextItems);
126-
})
127-
.join('');
125+
return generateContext(contextItems);
126+
})
127+
.join('');
128128

129129
if (useFullContext) {
130130
const prompt = `${header}

api/models/Agent.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ const loadEphemeralAgent = async ({ req, agent_id, endpoint, model_parameters: _
7070
if (ephemeralAgent?.execute_code === true) {
7171
tools.push(Tools.execute_code);
7272
}
73+
if (ephemeralAgent?.file_search === true) {
74+
tools.push(Tools.file_search);
75+
}
7376
if (ephemeralAgent?.web_search === true) {
7477
tools.push(Tools.web_search);
7578
}

api/models/Agent.spec.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ describe('models/Agent', () => {
4343
const mongoUri = mongoServer.getUri();
4444
Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
4545
await mongoose.connect(mongoUri);
46-
});
46+
}, 20000);
4747

4848
afterAll(async () => {
4949
await mongoose.disconnect();
@@ -413,7 +413,7 @@ describe('models/Agent', () => {
413413
const mongoUri = mongoServer.getUri();
414414
Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
415415
await mongoose.connect(mongoUri);
416-
});
416+
}, 20000);
417417

418418
afterAll(async () => {
419419
await mongoose.disconnect();
@@ -670,7 +670,7 @@ describe('models/Agent', () => {
670670
const mongoUri = mongoServer.getUri();
671671
Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
672672
await mongoose.connect(mongoUri);
673-
});
673+
}, 20000);
674674

675675
afterAll(async () => {
676676
await mongoose.disconnect();
@@ -1332,7 +1332,7 @@ describe('models/Agent', () => {
13321332
const mongoUri = mongoServer.getUri();
13331333
Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
13341334
await mongoose.connect(mongoUri);
1335-
});
1335+
}, 20000);
13361336

13371337
afterAll(async () => {
13381338
await mongoose.disconnect();
@@ -1514,7 +1514,7 @@ describe('models/Agent', () => {
15141514
const mongoUri = mongoServer.getUri();
15151515
Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
15161516
await mongoose.connect(mongoUri);
1517-
});
1517+
}, 20000);
15181518

15191519
afterAll(async () => {
15201520
await mongoose.disconnect();
@@ -1798,7 +1798,7 @@ describe('models/Agent', () => {
17981798
const mongoUri = mongoServer.getUri();
17991799
Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
18001800
await mongoose.connect(mongoUri);
1801-
});
1801+
}, 20000);
18021802

18031803
afterAll(async () => {
18041804
await mongoose.disconnect();
@@ -2350,7 +2350,7 @@ describe('models/Agent', () => {
23502350
const mongoUri = mongoServer.getUri();
23512351
Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
23522352
await mongoose.connect(mongoUri);
2353-
});
2353+
}, 20000);
23542354

23552355
afterAll(async () => {
23562356
await mongoose.disconnect();

0 commit comments

Comments
 (0)