From dcda6a249ce35f962c75ef7106d6298bcf2fc4a1 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Mon, 29 Dec 2025 21:42:21 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20refactor:=20Display=20name=20log?= =?UTF-8?q?ic=20in=20Parallel=20Responses=20(#11149)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Removed the use of `getResponseSender` for computing display names in both `Agent.js` and `loadAddedAgent.js`. - Implemented fallback logic to derive display names from `modelLabel`, `modelSpec.label`, and `endpointConfig.modelDisplayLabel`. - Enhanced comments for clarity on the new display name resolution process. - Updated `useChatFunctions` and `createDualMessageContent` to accommodate changes in sender logic, ensuring consistent handling of ephemeral agents across the application. --- api/models/Agent.js | 11 +++---- api/models/loadAddedAgent.js | 24 +++++++-------- client/src/hooks/Chat/useChatFunctions.ts | 3 ++ client/src/utils/messages.ts | 37 ++++++++++++++++------- 4 files changed, 46 insertions(+), 29 deletions(-) diff --git a/api/models/Agent.js b/api/models/Agent.js index b624f1430d..fd71ef282c 100644 --- a/api/models/Agent.js +++ b/api/models/Agent.js @@ -8,7 +8,6 @@ const { ResourceType, actionDelimiter, isAgentsEndpoint, - getResponseSender, isEphemeralAgentId, encodeEphemeralAgentId, } = require('librechat-data-provider'); @@ -150,7 +149,7 @@ const loadEphemeralAgent = async ({ req, spec, endpoint, model_parameters: _m }) const instructions = req.body.promptPrefix; - // Compute display name using getResponseSender (same logic used for addedConvo agents) + // Get endpoint config for modelDisplayLabel fallback const appConfig = req.config; let endpointConfig = appConfig?.endpoints?.[endpoint]; if (!isAgentsEndpoint(endpoint) && !endpointConfig) { @@ -161,10 +160,10 @@ const loadEphemeralAgent = async ({ req, spec, endpoint, model_parameters: _m }) } } - const sender = getResponseSender({ - modelLabel: model_parameters?.modelLabel, - modelDisplayLabel: endpointConfig?.modelDisplayLabel, - }); + // For ephemeral agents, use modelLabel if provided, then model spec's label, + // then modelDisplayLabel from endpoint config, otherwise empty string to show model name + const sender = + model_parameters?.modelLabel ?? modelSpec?.label ?? endpointConfig?.modelDisplayLabel ?? ''; // Encode ephemeral agent ID with endpoint, model, and computed sender for display const ephemeralId = encodeEphemeralAgentId({ endpoint, model, sender }); diff --git a/api/models/loadAddedAgent.js b/api/models/loadAddedAgent.js index 1678b2a558..aa83375eae 100644 --- a/api/models/loadAddedAgent.js +++ b/api/models/loadAddedAgent.js @@ -4,7 +4,6 @@ const { Tools, Constants, isAgentsEndpoint, - getResponseSender, isEphemeralAgentId, appendAgentIdSuffix, encodeEphemeralAgentId, @@ -81,7 +80,7 @@ const loadAddedAgent = async ({ req, conversation, primaryAgent }) => { // If both primary and added agents are ephemeral, duplicate tools from primary agent const primaryIsEphemeral = primaryAgent && isEphemeralAgentId(primaryAgent.id); if (primaryIsEphemeral && Array.isArray(primaryAgent.tools)) { - // Get display name using getResponseSender + // Get endpoint config and model spec for display name fallbacks const appConfig = req.config; let endpointConfig = appConfig?.endpoints?.[endpoint]; if (!isAgentsEndpoint(endpoint) && !endpointConfig) { @@ -92,10 +91,13 @@ const loadAddedAgent = async ({ req, conversation, primaryAgent }) => { } } - const sender = getResponseSender({ - modelLabel: rest.modelLabel, - modelDisplayLabel: endpointConfig?.modelDisplayLabel, - }); + // Look up model spec for label fallback + const modelSpecs = appConfig?.modelSpecs?.list; + const modelSpec = spec != null && spec !== '' ? modelSpecs?.find((s) => s.name === spec) : null; + + // For ephemeral agents, use modelLabel if provided, then model spec's label, + // then modelDisplayLabel from endpoint config, otherwise empty string to show model name + const sender = rest.modelLabel ?? modelSpec?.label ?? endpointConfig?.modelDisplayLabel ?? ''; const ephemeralId = encodeEphemeralAgentId({ endpoint, model, sender, index: 1 }); @@ -175,7 +177,7 @@ const loadAddedAgent = async ({ req, conversation, primaryAgent }) => { } } - // Get endpoint config for modelDisplayLabel (same pattern as initialize.js) + // Get endpoint config for modelDisplayLabel fallback const appConfig = req.config; let endpointConfig = appConfig?.endpoints?.[endpoint]; if (!isAgentsEndpoint(endpoint) && !endpointConfig) { @@ -186,11 +188,9 @@ const loadAddedAgent = async ({ req, conversation, primaryAgent }) => { } } - // Compute display name using getResponseSender (same logic used for main agent) - const sender = getResponseSender({ - modelLabel: rest.modelLabel, - modelDisplayLabel: endpointConfig?.modelDisplayLabel, - }); + // For ephemeral agents, use modelLabel if provided, then model spec's label, + // then modelDisplayLabel from endpoint config, otherwise empty string to show model name + const sender = rest.modelLabel ?? modelSpec?.label ?? endpointConfig?.modelDisplayLabel ?? ''; /** Encoded ephemeral agent ID with endpoint, model, sender, and index=1 to distinguish from primary */ const ephemeralId = encodeEphemeralAgentId({ endpoint, model, sender, index: 1 }); diff --git a/client/src/hooks/Chat/useChatFunctions.ts b/client/src/hooks/Chat/useChatFunctions.ts index 513688c9d3..8479d8eaac 100644 --- a/client/src/hooks/Chat/useChatFunctions.ts +++ b/client/src/hooks/Chat/useChatFunctions.ts @@ -18,6 +18,7 @@ import type { TMessage, TSubmission, TConversation, + TStartupConfig, TEndpointOption, TEndpointsConfig, EndpointSchemaKey, @@ -169,6 +170,7 @@ export default function useChatFunctions({ } const endpointsConfig = queryClient.getQueryData([QueryKeys.endpoints]); + const startupConfig = queryClient.getQueryData([QueryKeys.startupConfig]); const endpointType = getEndpointField(endpointsConfig, endpoint, 'type'); const iconURL = conversation?.iconURL; @@ -291,6 +293,7 @@ export default function useChatFunctions({ conversation, addedConvo, endpointsConfig, + startupConfig?.modelSpecs?.list, ); } else { initialResponse.content = []; diff --git a/client/src/utils/messages.ts b/client/src/utils/messages.ts index 2bffe2177c..7197b6c2db 100644 --- a/client/src/utils/messages.ts +++ b/client/src/utils/messages.ts @@ -2,7 +2,6 @@ import { QueryKeys, Constants, ContentTypes, - getResponseSender, isEphemeralAgentId, appendAgentIdSuffix, encodeEphemeralAgentId, @@ -199,12 +198,14 @@ export const getMessageAriaLabel = (message: TMessage, localize: LocalizeFunctio * @param primaryConvo - The primary conversation configuration * @param addedConvo - The added conversation configuration * @param endpointsConfig - Endpoints configuration for getting model display labels + * @param modelSpecs - Model specs list for getting spec labels * @returns Array of content parts with agentId for side-by-side rendering */ export const createDualMessageContent = ( primaryConvo: TConversation, addedConvo: TConversation, endpointsConfig?: TEndpointsConfig, + modelSpecs?: { name: string; label?: string }[], ): TMessageContentParts[] => { // For real agents (agent_id starts with "agent_"), use agent_id directly // Otherwise create ephemeral ID from endpoint/model @@ -214,11 +215,18 @@ export const createDualMessageContent = ( } else { const primaryEndpoint = primaryConvo.endpoint; const primaryModel = primaryConvo.model ?? ''; - const primarySender = getResponseSender({ - modelDisplayLabel: primaryEndpoint - ? endpointsConfig?.[primaryEndpoint]?.modelDisplayLabel - : undefined, - }); + // Look up model spec for label fallback + const primarySpec = + primaryConvo.spec != null && primaryConvo.spec !== '' + ? modelSpecs?.find((s) => s.name === primaryConvo.spec) + : undefined; + // For ephemeral agents, use modelLabel if provided, then model spec's label, + // then modelDisplayLabel from endpoint config, otherwise empty string to show model name + const primarySender = + primaryConvo.modelLabel ?? + primarySpec?.label ?? + (primaryEndpoint ? endpointsConfig?.[primaryEndpoint]?.modelDisplayLabel : undefined) ?? + ''; primaryAgentId = encodeEphemeralAgentId({ endpoint: primaryEndpoint ?? '', model: primaryModel, @@ -247,11 +255,18 @@ export const createDualMessageContent = ( } else { const addedEndpoint = addedConvo.endpoint; const addedModel = addedConvo.model ?? ''; - const addedSender = addedEndpoint - ? getResponseSender({ - modelDisplayLabel: endpointsConfig?.[addedEndpoint]?.modelDisplayLabel, - }) - : ''; + // Look up model spec for label fallback + const addedSpec = + addedConvo.spec != null && addedConvo.spec !== '' + ? modelSpecs?.find((s) => s.name === addedConvo.spec) + : undefined; + // For ephemeral agents, use modelLabel if provided, then model spec's label, + // then modelDisplayLabel from endpoint config, otherwise empty string to show model name + const addedSender = + addedConvo.modelLabel ?? + addedSpec?.label ?? + (addedEndpoint ? endpointsConfig?.[addedEndpoint]?.modelDisplayLabel : undefined) ?? + ''; addedAgentId = encodeEphemeralAgentId({ endpoint: addedEndpoint ?? '', model: addedModel,