mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-04-07 00:15:23 +02:00
🔧 feat: Lazy file provisioning — defer uploads to tool invocation time
Move file provisioning from eager (at chat-request start) to lazy (at tool invocation time via ON_TOOL_EXECUTE). Files are now only uploaded to code env / vector DB when the LLM actually calls the respective tool. - resources.ts: primeResources no longer provisions; computes provisionState (which files need code env / vector DB uploads) with staleness check and single credential load - handlers.ts: add provisionFiles callback to ToolExecuteOptions, called once per tool-call batch before execution - initialize.ts: pass provisionState through InitializedAgent - initialize.js: implement provisionFiles closure that provisions files in parallel, batches DB updates, clears state after use; store provisionState in agentToolContexts for all agent types
This commit is contained in:
parent
455d377600
commit
8684da106d
4 changed files with 144 additions and 122 deletions
|
|
@ -1,5 +1,5 @@
|
|||
const { logger } = require('@librechat/data-schemas');
|
||||
const { createContentAggregator } = require('@librechat/agents');
|
||||
const { Constants, createContentAggregator } = require('@librechat/agents');
|
||||
const {
|
||||
initializeAgent,
|
||||
validateAgentModel,
|
||||
|
|
@ -148,6 +148,70 @@ const initializeClient = async ({ req, res, signal, endpointOption }) => {
|
|||
return result;
|
||||
},
|
||||
toolEndCallback,
|
||||
provisionFiles: async (toolNames, agentId) => {
|
||||
const ctx = agentToolContexts.get(agentId);
|
||||
if (!ctx?.provisionState) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { provisionState, tool_resources } = ctx;
|
||||
const needsCode =
|
||||
toolNames.includes(Constants.EXECUTE_CODE) ||
|
||||
toolNames.includes(Constants.PROGRAMMATIC_TOOL_CALLING);
|
||||
const needsSearch = toolNames.includes('file_search');
|
||||
|
||||
if (!needsCode && !needsSearch) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @type {import('@librechat/api').TFileUpdate[]} */
|
||||
const pendingUpdates = [];
|
||||
|
||||
if (needsCode && provisionState.codeEnvFiles.length > 0 && provisionState.codeApiKey) {
|
||||
const results = await Promise.allSettled(
|
||||
provisionState.codeEnvFiles.map(async (file) => {
|
||||
const { fileIdentifier, fileUpdate } = await provisionToCodeEnv({
|
||||
req,
|
||||
file,
|
||||
entity_id: agentId,
|
||||
apiKey: provisionState.codeApiKey,
|
||||
});
|
||||
file.metadata = { ...file.metadata, fileIdentifier };
|
||||
pendingUpdates.push(fileUpdate);
|
||||
}),
|
||||
);
|
||||
for (const result of results) {
|
||||
if (result.status === 'rejected') {
|
||||
logger.error('[provisionFiles] Code env provisioning failed', result.reason);
|
||||
}
|
||||
}
|
||||
provisionState.codeEnvFiles = [];
|
||||
}
|
||||
|
||||
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 });
|
||||
if (result.embedded) {
|
||||
file.embedded = true;
|
||||
if (result.fileUpdate) {
|
||||
pendingUpdates.push(result.fileUpdate);
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
for (const result of results) {
|
||||
if (result.status === 'rejected') {
|
||||
logger.error('[provisionFiles] Vector DB provisioning failed', result.reason);
|
||||
}
|
||||
}
|
||||
provisionState.vectorDBFiles = [];
|
||||
}
|
||||
|
||||
if (pendingUpdates.length > 0) {
|
||||
await Promise.allSettled(pendingUpdates.map((update) => db.updateFile(update)));
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const summarizationOptions =
|
||||
|
|
@ -239,6 +303,7 @@ const initializeClient = async ({ req, res, signal, endpointOption }) => {
|
|||
userMCPAuthMap: primaryConfig.userMCPAuthMap,
|
||||
tool_resources: primaryConfig.tool_resources,
|
||||
actionsEnabled: primaryConfig.actionsEnabled,
|
||||
provisionState: primaryConfig.provisionState,
|
||||
});
|
||||
|
||||
const agent_ids = primaryConfig.agent_ids;
|
||||
|
|
@ -329,6 +394,7 @@ const initializeClient = async ({ req, res, signal, endpointOption }) => {
|
|||
userMCPAuthMap: config.userMCPAuthMap,
|
||||
tool_resources: config.tool_resources,
|
||||
actionsEnabled: config.actionsEnabled,
|
||||
provisionState: config.provisionState,
|
||||
});
|
||||
|
||||
agentConfigs.set(agentId, config);
|
||||
|
|
@ -412,6 +478,7 @@ const initializeClient = async ({ req, res, signal, endpointOption }) => {
|
|||
userMCPAuthMap: config.userMCPAuthMap,
|
||||
tool_resources: config.tool_resources,
|
||||
actionsEnabled: config.actionsEnabled,
|
||||
provisionState: config.provisionState,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue