mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-08-28 04:37:37 +00:00
📇 feat: Agent Contact Visibility with Owner Fallback (#13663)
* Shared Contract * Backend Resolution * Frontend Display * Contact Styling and more tests * fix contact flicker when saving an agent * fix display owner when contact deleted * simplification of the last fixes * github action fixes * fixes failing tests --------- Co-authored-by: Peter Rothlaender <peter.rothlaender@ginkgo.com>
This commit is contained in:
parent
376370d610
commit
abf9fc307d
19 changed files with 894 additions and 111 deletions
60
packages/api/src/agents/contact.spec.ts
Normal file
60
packages/api/src/agents/contact.spec.ts
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
import { resolveAgentOwnerContact } from './contact';
|
||||
|
||||
describe('resolveAgentOwnerContact', () => {
|
||||
it('omits owner fallback when support contact has a name', () => {
|
||||
const result = resolveAgentOwnerContact(
|
||||
{ support_contact: { name: 'Support Team' } },
|
||||
{ name: 'Agent Owner', email: 'owner@example.com' },
|
||||
);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('omits owner fallback when support contact has an email', () => {
|
||||
const result = resolveAgentOwnerContact(
|
||||
{ support_contact: { email: 'support@example.com' } },
|
||||
{ name: 'Agent Owner', email: 'owner@example.com' },
|
||||
);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('uses owner name and email when support contact is empty', () => {
|
||||
const result = resolveAgentOwnerContact(
|
||||
{ support_contact: { name: ' ', email: '' } },
|
||||
{ name: ' Agent Owner ', email: ' owner@example.com ' },
|
||||
);
|
||||
|
||||
expect(result).toEqual({ name: 'Agent Owner', email: 'owner@example.com' });
|
||||
});
|
||||
|
||||
it('falls back to username for owner display name', () => {
|
||||
const result = resolveAgentOwnerContact({}, { username: 'owner.user' });
|
||||
|
||||
expect(result).toEqual({ name: 'owner.user' });
|
||||
});
|
||||
|
||||
it('falls back to authorName when owner has no display name', () => {
|
||||
const result = resolveAgentOwnerContact(
|
||||
{ authorName: 'Legacy Author' },
|
||||
{ email: 'owner@example.com' },
|
||||
);
|
||||
|
||||
expect(result).toEqual({ name: 'Legacy Author', email: 'owner@example.com' });
|
||||
});
|
||||
|
||||
it('omits owner contact when no owner can be resolved', () => {
|
||||
const result = resolveAgentOwnerContact({ authorName: 'Legacy Author' }, null);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('omits owner contact when all candidate fields are empty', () => {
|
||||
const result = resolveAgentOwnerContact(
|
||||
{ authorName: ' ' },
|
||||
{ name: '', username: ' ', email: ' ' },
|
||||
);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
});
|
||||
55
packages/api/src/agents/contact.ts
Normal file
55
packages/api/src/agents/contact.ts
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import type { AgentOwnerContact } from 'librechat-data-provider';
|
||||
|
||||
export interface AgentContactSource {
|
||||
authorName?: string | null;
|
||||
support_contact?: {
|
||||
name?: string | null;
|
||||
email?: string | null;
|
||||
} | null;
|
||||
}
|
||||
|
||||
export interface AgentOwnerContactSource {
|
||||
name?: string | null;
|
||||
username?: string | null;
|
||||
email?: string | null;
|
||||
}
|
||||
|
||||
const normalizeContactValue = (value?: string | null): string | undefined => {
|
||||
if (typeof value !== 'string') {
|
||||
return undefined;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : undefined;
|
||||
};
|
||||
|
||||
export const hasSupportContact = (agent: AgentContactSource): boolean => {
|
||||
const support = agent.support_contact;
|
||||
if (!support) {
|
||||
return false;
|
||||
}
|
||||
return !!normalizeContactValue(support.name) || !!normalizeContactValue(support.email);
|
||||
};
|
||||
|
||||
export function resolveAgentOwnerContact(
|
||||
agent: AgentContactSource,
|
||||
owner: AgentOwnerContactSource | null,
|
||||
): AgentOwnerContact | undefined {
|
||||
if (hasSupportContact(agent) || owner == null) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const name =
|
||||
normalizeContactValue(owner.name) ??
|
||||
normalizeContactValue(owner.username) ??
|
||||
normalizeContactValue(agent.authorName);
|
||||
const email = normalizeContactValue(owner.email);
|
||||
|
||||
if (!name && !email) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
...(name ? { name } : {}),
|
||||
...(email ? { email } : {}),
|
||||
};
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ export * from './attachments';
|
|||
export * from './chain';
|
||||
export * from './client';
|
||||
export * from './config';
|
||||
export * from './contact';
|
||||
export * from './context';
|
||||
export * from './discovery';
|
||||
export * from './edges';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue