const { logger } = require('@librechat/data-schemas'); const { createContentAggregator } = require('@librechat/agents'); const { Constants, EModelEndpoint, getResponseSender } = require('librechat-data-provider'); const { getDefaultHandlers, createToolEndCallback, } = require('~/server/controllers/agents/callbacks'); const { initializeAgent } = require('~/server/services/Endpoints/agents/agent'); const { loadAgentTools } = require('~/server/services/ToolService'); const AgentClient = require('~/server/controllers/agents/client'); const { getAgent } = require('~/models/Agent'); function createToolLoader() { /** * @param {object} params * @param {ServerRequest} params.req * @param {ServerResponse} params.res * @param {string} params.agentId * @param {string[]} params.tools * @param {string} params.provider * @param {string} params.model * @param {AgentToolResources} params.tool_resources * @returns {Promise<{ tools: StructuredTool[], toolContextMap: Record } | undefined>} */ return async function loadTools({ req, res, agentId, tools, provider, model, tool_resources }) { const agent = { id: agentId, tools, provider, model }; try { return await loadAgentTools({ req, res, agent, tool_resources, }); } catch (error) { logger.error('Error loading tools for agent ' + agentId, error); } }; } const initializeClient = async ({ req, res, endpointOption }) => { if (!endpointOption) { throw new Error('Endpoint option not provided'); } // TODO: use endpointOption to determine options/modelOptions /** @type {Array} */ const collectedUsage = []; /** @type {ArtifactPromises} */ const artifactPromises = []; const { contentParts, aggregateContent } = createContentAggregator(); const toolEndCallback = createToolEndCallback({ req, res, artifactPromises }); const eventHandlers = getDefaultHandlers({ res, aggregateContent, toolEndCallback, collectedUsage, }); if (!endpointOption.agent) { throw new Error('No agent promise provided'); } const primaryAgent = await endpointOption.agent; if (!primaryAgent) { throw new Error('Agent not found'); } const agentConfigs = new Map(); /** @type {Set} */ const allowedProviders = new Set(req?.app?.locals?.[EModelEndpoint.agents]?.allowedProviders); const loadTools = createToolLoader(); /** @type {Array} */ const requestFiles = req.body.files ?? []; /** @type {string} */ const conversationId = req.body.conversationId; const primaryConfig = await initializeAgent({ req, res, loadTools, requestFiles, conversationId, agent: primaryAgent, endpointOption, allowedProviders, isInitialAgent: true, }); const agent_ids = primaryConfig.agent_ids; if (agent_ids?.length) { for (const agentId of agent_ids) { const agent = await getAgent({ id: agentId }); if (!agent) { throw new Error(`Agent ${agentId} not found`); } const config = await initializeAgent({ req, res, agent, loadTools, requestFiles, conversationId, endpointOption, allowedProviders, }); agentConfigs.set(agentId, config); } } const sender = primaryAgent.name ?? getResponseSender({ ...endpointOption, model: endpointOption.model_parameters.model, }); const client = new AgentClient({ req, res, sender, contentParts, agentConfigs, eventHandlers, collectedUsage, aggregateContent, artifactPromises, agent: primaryConfig, spec: endpointOption.spec, iconURL: endpointOption.iconURL, attachments: primaryConfig.attachments, endpointType: endpointOption.endpointType, maxContextTokens: primaryConfig.maxContextTokens, resendFiles: primaryConfig.model_parameters?.resendFiles ?? true, endpoint: primaryConfig.id === Constants.EPHEMERAL_AGENT_ID ? primaryConfig.endpoint : EModelEndpoint.agents, }); return { client }; }; module.exports = { initializeClient };