diff --git a/api/server/services/Endpoints/agents/initialize.js b/api/server/services/Endpoints/agents/initialize.js index 39faef6814..a40c0d5e71 100644 --- a/api/server/services/Endpoints/agents/initialize.js +++ b/api/server/services/Endpoints/agents/initialize.js @@ -17,9 +17,11 @@ const { buildAgentContextAttachmentsByAgentId, } = require('@librechat/api'); const { + FileContext, Permissions, ResourceType, EModelEndpoint, + EToolResources, PermissionBits, PermissionTypes, MAX_SUBAGENT_DEPTH, @@ -275,6 +277,29 @@ const initializeClient = async ({ req, res, signal, endpointOption }) => { return; } + /** Current-message chat attachments stay in the user's sandbox / unscoped vector + * index (matching the direct message_file upload path); only agent setup files + * are scoped to the agent. */ + const entityIdForFile = (file) => + file.context === FileContext.message_attachment ? undefined : agentId; + + /** Surface a just-provisioned file to the tool loaded immediately after: the code + * and file_search primers read `tool_resources..files`. */ + if (!ctx.tool_resources) { + ctx.tool_resources = {}; + } + const addProvisionedFile = (file, resourceType) => { + if (!file.file_id) { + return; + } + const resource = ctx.tool_resources[resourceType] ?? {}; + const files = resource.files ? [...resource.files] : []; + if (!files.some((existing) => existing.file_id === file.file_id)) { + files.push(file); + } + ctx.tool_resources[resourceType] = { ...resource, files }; + }; + /** @type {import('@librechat/api').TFileUpdate[]} */ const pendingUpdates = []; @@ -284,9 +309,10 @@ const initializeClient = async ({ req, res, signal, endpointOption }) => { const { codeEnvRef, fileUpdate } = await provisionToCodeEnv({ req, file, - entity_id: agentId, + entity_id: entityIdForFile(file), }); file.metadata = { ...file.metadata, codeEnvRef }; + addProvisionedFile(file, EToolResources.execute_code); pendingUpdates.push(fileUpdate); }), ); @@ -301,9 +327,14 @@ const initializeClient = async ({ req, res, signal, endpointOption }) => { if (needsSearch && provisionState.vectorDBFiles.length > 0) { const results = await Promise.allSettled( provisionState.vectorDBFiles.map(async (file) => { - const result = await provisionToVectorDB({ req, file, entity_id: agentId }); + const result = await provisionToVectorDB({ + req, + file, + entity_id: entityIdForFile(file), + }); if (result.embedded) { file.embedded = true; + addProvisionedFile(file, EToolResources.file_search); if (result.fileUpdate) { pendingUpdates.push(result.fileUpdate); }