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,