mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 08:50:15 +01:00
🐞 fix: Agent "Resend" Message Attachments + Source Icon Styling (#6408)
* style: Update text file source icon background color for improved visibility in light mode * style: Update `vectordb` source icon background color for better visibility * fix: resend files behavior for tool resource message attachments (code interpreter and file search); Rename `getToolFiles` to `getConvoFiles` and simplify file retrieval logic; add `getToolFilesByIds` for fetching tool files by IDs
This commit is contained in:
parent
8f68e8be81
commit
57c3a217c6
4 changed files with 46 additions and 38 deletions
|
|
@ -61,45 +61,22 @@ const deleteNullOrEmptyConversations = async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves files from a conversation that have either embedded=true
|
* Searches for a conversation by conversationId and returns associated file ids.
|
||||||
* or a metadata.fileIdentifier. Simplified and efficient query.
|
* @param {string} conversationId - The conversation's ID.
|
||||||
*
|
* @returns {Promise<string[] | null>}
|
||||||
* @param {string} conversationId - The conversation ID
|
|
||||||
* @returns {Promise<MongoFile[]>} - Filtered array of matching file objects
|
|
||||||
*/
|
*/
|
||||||
const getToolFiles = async (conversationId) => {
|
const getConvoFiles = async (conversationId) => {
|
||||||
try {
|
try {
|
||||||
const [result] = await Conversation.aggregate([
|
return (await Conversation.findOne({ conversationId }, 'files').lean())?.files ?? [];
|
||||||
{ $match: { conversationId } },
|
|
||||||
{
|
|
||||||
$project: {
|
|
||||||
files: {
|
|
||||||
$filter: {
|
|
||||||
input: '$files',
|
|
||||||
as: 'file',
|
|
||||||
cond: {
|
|
||||||
$or: [
|
|
||||||
{ $eq: ['$$file.embedded', true] },
|
|
||||||
{ $ifNull: ['$$file.metadata.fileIdentifier', false] },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
_id: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]).exec();
|
|
||||||
|
|
||||||
return result?.files || [];
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('[getConvoEmbeddedFiles] Error fetching embedded files:', error);
|
logger.error('[getConvoFiles] Error getting conversation files', error);
|
||||||
throw new Error('Error fetching embedded files');
|
throw new Error('Error getting conversation files');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Conversation,
|
Conversation,
|
||||||
getToolFiles,
|
getConvoFiles,
|
||||||
searchConversation,
|
searchConversation,
|
||||||
deleteNullOrEmptyConversations,
|
deleteNullOrEmptyConversations,
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const { fileSchema } = require('@librechat/data-schemas');
|
const { fileSchema } = require('@librechat/data-schemas');
|
||||||
|
const { logger } = require('~/config');
|
||||||
|
|
||||||
const File = mongoose.model('File', fileSchema);
|
const File = mongoose.model('File', fileSchema);
|
||||||
|
|
||||||
|
|
@ -26,6 +27,32 @@ const getFiles = async (filter, _sortOptions, selectFields = { text: 0 }) => {
|
||||||
return await File.find(filter).select(selectFields).sort(sortOptions).lean();
|
return await File.find(filter).select(selectFields).sort(sortOptions).lean();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves tool files (files that are embedded or have a fileIdentifier) from an array of file IDs
|
||||||
|
* @param {string[]} fileIds - Array of file_id strings to search for
|
||||||
|
* @returns {Promise<Array<IMongoFile>>} Files that match the criteria
|
||||||
|
*/
|
||||||
|
const getToolFilesByIds = async (fileIds) => {
|
||||||
|
if (!fileIds || !fileIds.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const filter = {
|
||||||
|
file_id: { $in: fileIds },
|
||||||
|
$or: [{ embedded: true }, { 'metadata.fileIdentifier': { $exists: true } }],
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectFields = { text: 0 };
|
||||||
|
const sortOptions = { updatedAt: -1 };
|
||||||
|
|
||||||
|
return await getFiles(filter, sortOptions, selectFields);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('[getToolFilesByIds] Error retrieving tool files:', error);
|
||||||
|
throw new Error('Error retrieving tool files');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new file with a TTL of 1 hour.
|
* Creates a new file with a TTL of 1 hour.
|
||||||
* @param {IMongoFile} data - The file data to be created, must contain file_id.
|
* @param {IMongoFile} data - The file data to be created, must contain file_id.
|
||||||
|
|
@ -111,6 +138,7 @@ module.exports = {
|
||||||
File,
|
File,
|
||||||
findFileById,
|
findFileById,
|
||||||
getFiles,
|
getFiles,
|
||||||
|
getToolFilesByIds,
|
||||||
createFile,
|
createFile,
|
||||||
updateFile,
|
updateFile,
|
||||||
updateFileUsage,
|
updateFileUsage,
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@ const { getCustomEndpointConfig } = require('~/server/services/Config');
|
||||||
const { processFiles } = require('~/server/services/Files/process');
|
const { processFiles } = require('~/server/services/Files/process');
|
||||||
const { loadAgentTools } = require('~/server/services/ToolService');
|
const { loadAgentTools } = require('~/server/services/ToolService');
|
||||||
const AgentClient = require('~/server/controllers/agents/client');
|
const AgentClient = require('~/server/controllers/agents/client');
|
||||||
const { getToolFiles } = require('~/models/Conversation');
|
const { getConvoFiles } = require('~/models/Conversation');
|
||||||
|
const { getToolFilesByIds } = require('~/models/File');
|
||||||
const { getModelMaxTokens } = require('~/utils');
|
const { getModelMaxTokens } = require('~/utils');
|
||||||
const { getAgent } = require('~/models/Agent');
|
const { getAgent } = require('~/models/Agent');
|
||||||
const { getFiles } = require('~/models/File');
|
const { getFiles } = require('~/models/File');
|
||||||
|
|
@ -115,15 +116,17 @@ const initializeAgentOptions = async ({
|
||||||
isInitialAgent = false,
|
isInitialAgent = false,
|
||||||
}) => {
|
}) => {
|
||||||
let currentFiles;
|
let currentFiles;
|
||||||
|
/** @type {Array<MongoFile>} */
|
||||||
const requestFiles = req.body.files ?? [];
|
const requestFiles = req.body.files ?? [];
|
||||||
if (
|
if (
|
||||||
isInitialAgent &&
|
isInitialAgent &&
|
||||||
req.body.conversationId != null &&
|
req.body.conversationId != null &&
|
||||||
agent.model_parameters?.resendFiles === true
|
(agent.model_parameters?.resendFiles ?? true) === true
|
||||||
) {
|
) {
|
||||||
const fileIds = (await getToolFiles(req.body.conversationId)).map((f) => f.file_id);
|
const fileIds = (await getConvoFiles(req.body.conversationId)) ?? [];
|
||||||
if (requestFiles.length || fileIds.length) {
|
const toolFiles = await getToolFilesByIds(fileIds);
|
||||||
currentFiles = await processFiles(requestFiles, fileIds);
|
if (requestFiles.length || toolFiles.length) {
|
||||||
|
currentFiles = await processFiles(requestFiles.concat(toolFiles));
|
||||||
}
|
}
|
||||||
} else if (isInitialAgent && requestFiles.length) {
|
} else if (isInitialAgent && requestFiles.length) {
|
||||||
currentFiles = await processFiles(requestFiles);
|
currentFiles = await processFiles(requestFiles);
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ const sourceToClassname = {
|
||||||
[FileSources.openai]: 'bg-white/75 dark:bg-black/65',
|
[FileSources.openai]: 'bg-white/75 dark:bg-black/65',
|
||||||
[FileSources.azure]: 'azure-bg-color opacity-85',
|
[FileSources.azure]: 'azure-bg-color opacity-85',
|
||||||
[FileSources.execute_code]: 'bg-black text-white opacity-85',
|
[FileSources.execute_code]: 'bg-black text-white opacity-85',
|
||||||
[FileSources.text]: 'bg-blue-100 dark:bg-blue-900 opacity-85 text-white',
|
[FileSources.text]: 'bg-blue-500 dark:bg-blue-900 opacity-85 text-white',
|
||||||
[FileSources.vectordb]: 'bg-yellow-100 dark:bg-yellow-900 opacity-85 text-white',
|
[FileSources.vectordb]: 'bg-yellow-700 dark:bg-yellow-900 opacity-85 text-white',
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultClassName =
|
const defaultClassName =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue