📚 feat: Add Source Citations for File Search in Agents (#8652)

* feat: Source Citations for file_search in Agents

* Fix: Added citation limits and relevance score to app service. Removed duplicate tests

*  feat: implement Role-level toggle to optionally disable file Source Citation in Agents

* 🐛 fix: update mock for librechat-data-provider to include PermissionTypes and SystemRoles

---------

Co-authored-by: “Praneeth <praneeth.goparaju@slalom.com>
This commit is contained in:
Danny Avila 2025-07-25 00:07:37 -04:00
parent a955097faf
commit 52e59e40be
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
36 changed files with 1890 additions and 190 deletions

View file

@ -49,6 +49,7 @@ const BaseClient = require('~/app/clients/BaseClient');
const { getRoleByName } = require('~/models/Role');
const { loadAgent } = require('~/models/Agent');
const { getMCPManager } = require('~/config');
const { processAgentResponse } = require('~/app/clients/agents/processAgentResponse');
const omitTitleOptions = new Set([
'stream',
@ -838,7 +839,7 @@ class AgentClient extends BaseClient {
if (noSystemMessages === true && systemContent?.length) {
const latestMessageContent = _messages.pop().content;
if (typeof latestMessage !== 'string') {
if (typeof latestMessageContent !== 'string') {
latestMessageContent[0].text = [systemContent, latestMessageContent[0].text].join('\n');
_messages.push(new HumanMessage({ content: latestMessageContent }));
} else {
@ -1034,6 +1035,28 @@ class AgentClient extends BaseClient {
if (attachments && attachments.length > 0) {
this.artifactPromises.push(...attachments);
}
// Process agent response to capture file references and create attachments
const processedResponse = await processAgentResponse(
{
messageId: this.responseMessageId,
attachments: this.artifactPromises,
},
this.user ?? this.options.req.user?.id,
this.conversationId,
this.contentParts,
this.options.req.user,
);
// Update artifact promises with any new attachments from agent response
if (processedResponse.attachments && processedResponse.attachments.length > 0) {
// Add new attachments to existing artifactPromises
processedResponse.attachments.forEach((attachment) => {
this.artifactPromises.push(Promise.resolve(attachment));
});
}
await this.recordCollectedUsage({ context: 'message' });
} catch (err) {
logger.error(