🔧 refactor: Display name logic in Parallel Responses (#11149)

- 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.
This commit is contained in:
Danny Avila 2025-12-29 21:42:21 -05:00 committed by GitHub
parent c7469ce884
commit dcda6a249c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 46 additions and 29 deletions

View file

@ -8,7 +8,6 @@ const {
ResourceType, ResourceType,
actionDelimiter, actionDelimiter,
isAgentsEndpoint, isAgentsEndpoint,
getResponseSender,
isEphemeralAgentId, isEphemeralAgentId,
encodeEphemeralAgentId, encodeEphemeralAgentId,
} = require('librechat-data-provider'); } = require('librechat-data-provider');
@ -150,7 +149,7 @@ const loadEphemeralAgent = async ({ req, spec, endpoint, model_parameters: _m })
const instructions = req.body.promptPrefix; 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; const appConfig = req.config;
let endpointConfig = appConfig?.endpoints?.[endpoint]; let endpointConfig = appConfig?.endpoints?.[endpoint];
if (!isAgentsEndpoint(endpoint) && !endpointConfig) { if (!isAgentsEndpoint(endpoint) && !endpointConfig) {
@ -161,10 +160,10 @@ const loadEphemeralAgent = async ({ req, spec, endpoint, model_parameters: _m })
} }
} }
const sender = getResponseSender({ // For ephemeral agents, use modelLabel if provided, then model spec's label,
modelLabel: model_parameters?.modelLabel, // then modelDisplayLabel from endpoint config, otherwise empty string to show model name
modelDisplayLabel: endpointConfig?.modelDisplayLabel, const sender =
}); model_parameters?.modelLabel ?? modelSpec?.label ?? endpointConfig?.modelDisplayLabel ?? '';
// Encode ephemeral agent ID with endpoint, model, and computed sender for display // Encode ephemeral agent ID with endpoint, model, and computed sender for display
const ephemeralId = encodeEphemeralAgentId({ endpoint, model, sender }); const ephemeralId = encodeEphemeralAgentId({ endpoint, model, sender });

View file

@ -4,7 +4,6 @@ const {
Tools, Tools,
Constants, Constants,
isAgentsEndpoint, isAgentsEndpoint,
getResponseSender,
isEphemeralAgentId, isEphemeralAgentId,
appendAgentIdSuffix, appendAgentIdSuffix,
encodeEphemeralAgentId, encodeEphemeralAgentId,
@ -81,7 +80,7 @@ const loadAddedAgent = async ({ req, conversation, primaryAgent }) => {
// If both primary and added agents are ephemeral, duplicate tools from primary agent // If both primary and added agents are ephemeral, duplicate tools from primary agent
const primaryIsEphemeral = primaryAgent && isEphemeralAgentId(primaryAgent.id); const primaryIsEphemeral = primaryAgent && isEphemeralAgentId(primaryAgent.id);
if (primaryIsEphemeral && Array.isArray(primaryAgent.tools)) { 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; const appConfig = req.config;
let endpointConfig = appConfig?.endpoints?.[endpoint]; let endpointConfig = appConfig?.endpoints?.[endpoint];
if (!isAgentsEndpoint(endpoint) && !endpointConfig) { if (!isAgentsEndpoint(endpoint) && !endpointConfig) {
@ -92,10 +91,13 @@ const loadAddedAgent = async ({ req, conversation, primaryAgent }) => {
} }
} }
const sender = getResponseSender({ // Look up model spec for label fallback
modelLabel: rest.modelLabel, const modelSpecs = appConfig?.modelSpecs?.list;
modelDisplayLabel: endpointConfig?.modelDisplayLabel, 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 }); 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; const appConfig = req.config;
let endpointConfig = appConfig?.endpoints?.[endpoint]; let endpointConfig = appConfig?.endpoints?.[endpoint];
if (!isAgentsEndpoint(endpoint) && !endpointConfig) { 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) // For ephemeral agents, use modelLabel if provided, then model spec's label,
const sender = getResponseSender({ // then modelDisplayLabel from endpoint config, otherwise empty string to show model name
modelLabel: rest.modelLabel, const sender = rest.modelLabel ?? modelSpec?.label ?? endpointConfig?.modelDisplayLabel ?? '';
modelDisplayLabel: endpointConfig?.modelDisplayLabel,
});
/** Encoded ephemeral agent ID with endpoint, model, sender, and index=1 to distinguish from primary */ /** Encoded ephemeral agent ID with endpoint, model, sender, and index=1 to distinguish from primary */
const ephemeralId = encodeEphemeralAgentId({ endpoint, model, sender, index: 1 }); const ephemeralId = encodeEphemeralAgentId({ endpoint, model, sender, index: 1 });

View file

@ -18,6 +18,7 @@ import type {
TMessage, TMessage,
TSubmission, TSubmission,
TConversation, TConversation,
TStartupConfig,
TEndpointOption, TEndpointOption,
TEndpointsConfig, TEndpointsConfig,
EndpointSchemaKey, EndpointSchemaKey,
@ -169,6 +170,7 @@ export default function useChatFunctions({
} }
const endpointsConfig = queryClient.getQueryData<TEndpointsConfig>([QueryKeys.endpoints]); const endpointsConfig = queryClient.getQueryData<TEndpointsConfig>([QueryKeys.endpoints]);
const startupConfig = queryClient.getQueryData<TStartupConfig>([QueryKeys.startupConfig]);
const endpointType = getEndpointField(endpointsConfig, endpoint, 'type'); const endpointType = getEndpointField(endpointsConfig, endpoint, 'type');
const iconURL = conversation?.iconURL; const iconURL = conversation?.iconURL;
@ -291,6 +293,7 @@ export default function useChatFunctions({
conversation, conversation,
addedConvo, addedConvo,
endpointsConfig, endpointsConfig,
startupConfig?.modelSpecs?.list,
); );
} else { } else {
initialResponse.content = []; initialResponse.content = [];

View file

@ -2,7 +2,6 @@ import {
QueryKeys, QueryKeys,
Constants, Constants,
ContentTypes, ContentTypes,
getResponseSender,
isEphemeralAgentId, isEphemeralAgentId,
appendAgentIdSuffix, appendAgentIdSuffix,
encodeEphemeralAgentId, encodeEphemeralAgentId,
@ -199,12 +198,14 @@ export const getMessageAriaLabel = (message: TMessage, localize: LocalizeFunctio
* @param primaryConvo - The primary conversation configuration * @param primaryConvo - The primary conversation configuration
* @param addedConvo - The added conversation configuration * @param addedConvo - The added conversation configuration
* @param endpointsConfig - Endpoints configuration for getting model display labels * @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 * @returns Array of content parts with agentId for side-by-side rendering
*/ */
export const createDualMessageContent = ( export const createDualMessageContent = (
primaryConvo: TConversation, primaryConvo: TConversation,
addedConvo: TConversation, addedConvo: TConversation,
endpointsConfig?: TEndpointsConfig, endpointsConfig?: TEndpointsConfig,
modelSpecs?: { name: string; label?: string }[],
): TMessageContentParts[] => { ): TMessageContentParts[] => {
// For real agents (agent_id starts with "agent_"), use agent_id directly // For real agents (agent_id starts with "agent_"), use agent_id directly
// Otherwise create ephemeral ID from endpoint/model // Otherwise create ephemeral ID from endpoint/model
@ -214,11 +215,18 @@ export const createDualMessageContent = (
} else { } else {
const primaryEndpoint = primaryConvo.endpoint; const primaryEndpoint = primaryConvo.endpoint;
const primaryModel = primaryConvo.model ?? ''; const primaryModel = primaryConvo.model ?? '';
const primarySender = getResponseSender({ // Look up model spec for label fallback
modelDisplayLabel: primaryEndpoint const primarySpec =
? endpointsConfig?.[primaryEndpoint]?.modelDisplayLabel primaryConvo.spec != null && primaryConvo.spec !== ''
: undefined, ? 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({ primaryAgentId = encodeEphemeralAgentId({
endpoint: primaryEndpoint ?? '', endpoint: primaryEndpoint ?? '',
model: primaryModel, model: primaryModel,
@ -247,11 +255,18 @@ export const createDualMessageContent = (
} else { } else {
const addedEndpoint = addedConvo.endpoint; const addedEndpoint = addedConvo.endpoint;
const addedModel = addedConvo.model ?? ''; const addedModel = addedConvo.model ?? '';
const addedSender = addedEndpoint // Look up model spec for label fallback
? getResponseSender({ const addedSpec =
modelDisplayLabel: endpointsConfig?.[addedEndpoint]?.modelDisplayLabel, 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({ addedAgentId = encodeEphemeralAgentId({
endpoint: addedEndpoint ?? '', endpoint: addedEndpoint ?? '',
model: addedModel, model: addedModel,