mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-09-10 16:40:42 +00:00
🐛 fix: Retain auto-routed context uploads and isolate vector temp files
An agent upload with no explicit tool_resource that resolves to the text path is promoted to a context resource, but retention still received the original undefined tool_resource, so in retention modes that expire conversation files while keeping persistent agent resources these files were given an expiration and swept. Vector provisioning also derived its temp path from file_id alone, so two concurrent requests for the same file shared one path and could unlink or truncate it mid-stream, producing failed or corrupted embeddings.
This commit is contained in:
parent
bc2e9c868f
commit
2cd5076f50
3 changed files with 27 additions and 3 deletions
|
|
@ -899,7 +899,7 @@ const processAgentFileUpload = async ({ req, res, metadata, sseStream }) => {
|
|||
const retentionExpiry = await getAgentFileRetentionExpiry({
|
||||
req,
|
||||
messageAttachment,
|
||||
tool_resource,
|
||||
tool_resource: effectiveToolResource,
|
||||
});
|
||||
|
||||
const fileInfo = {
|
||||
|
|
@ -1149,7 +1149,7 @@ const processAgentFileUpload = async ({ req, res, metadata, sseStream }) => {
|
|||
const retentionExpiry = await getAgentFileRetentionExpiry({
|
||||
req,
|
||||
messageAttachment,
|
||||
tool_resource,
|
||||
tool_resource: effectiveToolResource,
|
||||
});
|
||||
const fileInfo = {
|
||||
...removeNullishValues({
|
||||
|
|
|
|||
|
|
@ -1530,6 +1530,23 @@ describe('processAgentFileUpload', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('retains an auto-routed context upload as an agent resource', async () => {
|
||||
const { getAgentFileRetentionExpiry } = require('@librechat/api');
|
||||
mergeFileConfig.mockReturnValue(makeFileConfig());
|
||||
const req = makeReq({ mimetype: DOCX_MIME, ocrConfig: null });
|
||||
|
||||
await processAgentFileUpload({
|
||||
req,
|
||||
res: mockRes,
|
||||
metadata: { agent_id: 'agent-abc', file_id: 'file-uuid-123' },
|
||||
}).catch(() => {});
|
||||
|
||||
expect(getAgentFileRetentionExpiry).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ toolResource: EToolResources.context }),
|
||||
expect.any(Object),
|
||||
);
|
||||
});
|
||||
|
||||
test('plans extraction with the promoted context resource for auto-routed text uploads', async () => {
|
||||
const { getUploadExtractedTextPlan } = require('@librechat/api');
|
||||
mergeFileConfig.mockReturnValue(makeFileConfig());
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const { randomUUID } = require('crypto');
|
||||
const { getCodeBaseURL } = require('@librechat/agents');
|
||||
const {
|
||||
logAxiosError,
|
||||
|
|
@ -168,7 +169,13 @@ async function provisionToVectorDB({ req, file, entity_id, existingStream }) {
|
|||
return { embedded: false, fileUpdate: null };
|
||||
}
|
||||
|
||||
const tmpPath = path.join(os.tmpdir(), `provision-${file.file_id}${path.extname(file.filename)}`);
|
||||
/* Unique per attempt: two concurrent requests provisioning the same file_id would
|
||||
* otherwise share one path, and the first to finish unlinks it while the second is
|
||||
* still streaming into uploadVectors. */
|
||||
const tmpPath = path.join(
|
||||
os.tmpdir(),
|
||||
`provision-${file.file_id}-${randomUUID()}${path.extname(file.filename)}`,
|
||||
);
|
||||
|
||||
try {
|
||||
let stream = existingStream;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue