mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-04-07 08:25:23 +02:00
- Extract `specDisplayFieldReset` constant and `mergeQuerySettingsWithSpec` utility to `client/src/utils/endpoints.ts` as a single source of truth for spec display fields that must be cleared on non-spec transitions. - Clear `spec`, `iconURL`, `modelLabel`, and `greeting` from the merged preset in `ChatRoute.getNewConvoPreset()` when URL query parameters override the conversation without explicitly setting a spec. - Also clear `greeting` in the parallel cleanup in `useQueryParams.newQueryConvo` using the shared `specDisplayFieldReset` constant. - Guard the field reset on `specPreset != null` so null values aren't injected when no spec is configured. - Add comprehensive test coverage for the merge-and-clear logic.
152 lines
5.1 KiB
TypeScript
152 lines
5.1 KiB
TypeScript
import { EModelEndpoint } from 'librechat-data-provider';
|
|
import type { TPreset } from 'librechat-data-provider';
|
|
import { mergeQuerySettingsWithSpec, specDisplayFieldReset } from '../endpoints';
|
|
|
|
describe('mergeQuerySettingsWithSpec', () => {
|
|
const specPreset: TPreset = {
|
|
endpoint: EModelEndpoint.openAI,
|
|
model: 'gpt-4',
|
|
spec: 'my-spec',
|
|
iconURL: 'https://example.com/icon.png',
|
|
modelLabel: 'My Custom GPT',
|
|
greeting: 'Hello from the spec!',
|
|
temperature: 0.7,
|
|
};
|
|
|
|
describe('when specPreset is active and query has no spec', () => {
|
|
it('clears all spec display fields for agent share links', () => {
|
|
const querySettings: TPreset = {
|
|
agent_id: 'agent_123',
|
|
endpoint: EModelEndpoint.agents,
|
|
};
|
|
|
|
const result = mergeQuerySettingsWithSpec(specPreset, querySettings);
|
|
|
|
expect(result.agent_id).toBe('agent_123');
|
|
expect(result.endpoint).toBe(EModelEndpoint.agents);
|
|
expect(result.spec).toBeNull();
|
|
expect(result.iconURL).toBeNull();
|
|
expect(result.modelLabel).toBeNull();
|
|
expect(result.greeting).toBeUndefined();
|
|
});
|
|
|
|
it('preserves non-display settings from the spec base', () => {
|
|
const querySettings: TPreset = {
|
|
agent_id: 'agent_123',
|
|
endpoint: EModelEndpoint.agents,
|
|
};
|
|
|
|
const result = mergeQuerySettingsWithSpec(specPreset, querySettings);
|
|
|
|
expect(result.temperature).toBe(0.7);
|
|
});
|
|
|
|
it('clears spec display fields for assistant share links', () => {
|
|
const querySettings: TPreset = {
|
|
assistant_id: 'asst_abc',
|
|
endpoint: EModelEndpoint.assistants,
|
|
};
|
|
|
|
const result = mergeQuerySettingsWithSpec(specPreset, querySettings);
|
|
|
|
expect(result.assistant_id).toBe('asst_abc');
|
|
expect(result.endpoint).toBe(EModelEndpoint.assistants);
|
|
expect(result.spec).toBeNull();
|
|
expect(result.iconURL).toBeNull();
|
|
expect(result.modelLabel).toBeNull();
|
|
expect(result.greeting).toBeUndefined();
|
|
});
|
|
|
|
it('clears spec display fields for model override links', () => {
|
|
const querySettings: TPreset = {
|
|
model: 'claude-sonnet-4-20250514',
|
|
endpoint: EModelEndpoint.anthropic,
|
|
};
|
|
|
|
const result = mergeQuerySettingsWithSpec(specPreset, querySettings);
|
|
|
|
expect(result.model).toBe('claude-sonnet-4-20250514');
|
|
expect(result.endpoint).toBe(EModelEndpoint.anthropic);
|
|
expect(result.spec).toBeNull();
|
|
expect(result.iconURL).toBeNull();
|
|
expect(result.modelLabel).toBeNull();
|
|
expect(result.greeting).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('when query explicitly sets a spec', () => {
|
|
it('preserves spec display fields from the base', () => {
|
|
const querySettings = { spec: 'other-spec' } as TPreset;
|
|
|
|
const result = mergeQuerySettingsWithSpec(specPreset, querySettings);
|
|
|
|
expect(result.spec).toBe('other-spec');
|
|
expect(result.iconURL).toBe('https://example.com/icon.png');
|
|
expect(result.modelLabel).toBe('My Custom GPT');
|
|
expect(result.greeting).toBe('Hello from the spec!');
|
|
});
|
|
});
|
|
|
|
describe('when specPreset is undefined (no spec configured)', () => {
|
|
it('returns querySettings without injecting null display fields', () => {
|
|
const querySettings: TPreset = {
|
|
agent_id: 'agent_123',
|
|
endpoint: EModelEndpoint.agents,
|
|
};
|
|
|
|
const result = mergeQuerySettingsWithSpec(undefined, querySettings);
|
|
|
|
expect(result.agent_id).toBe('agent_123');
|
|
expect(result.endpoint).toBe(EModelEndpoint.agents);
|
|
expect(result).not.toHaveProperty('spec');
|
|
expect(result).not.toHaveProperty('iconURL');
|
|
expect(result).not.toHaveProperty('modelLabel');
|
|
expect(result).not.toHaveProperty('greeting');
|
|
});
|
|
});
|
|
|
|
describe('when querySettings is empty', () => {
|
|
it('still clears spec display fields (no query params is not an explicit spec)', () => {
|
|
const result = mergeQuerySettingsWithSpec(specPreset, {} as TPreset);
|
|
|
|
expect(result.spec).toBeNull();
|
|
expect(result.iconURL).toBeNull();
|
|
expect(result.modelLabel).toBeNull();
|
|
expect(result.greeting).toBeUndefined();
|
|
expect(result.endpoint).toBe(EModelEndpoint.openAI);
|
|
expect(result.model).toBe('gpt-4');
|
|
expect(result.temperature).toBe(0.7);
|
|
});
|
|
});
|
|
|
|
describe('query settings override spec values', () => {
|
|
it('overrides endpoint and model from spec', () => {
|
|
const querySettings: TPreset = {
|
|
endpoint: EModelEndpoint.anthropic,
|
|
model: 'claude-sonnet-4-20250514',
|
|
};
|
|
|
|
const result = mergeQuerySettingsWithSpec(specPreset, querySettings);
|
|
|
|
expect(result.endpoint).toBe(EModelEndpoint.anthropic);
|
|
expect(result.model).toBe('claude-sonnet-4-20250514');
|
|
expect(result.temperature).toBe(0.7);
|
|
expect(result.spec).toBeNull();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('specDisplayFieldReset', () => {
|
|
it('contains all spec display fields that need clearing', () => {
|
|
expect(specDisplayFieldReset).toEqual({
|
|
spec: null,
|
|
iconURL: null,
|
|
modelLabel: null,
|
|
greeting: undefined,
|
|
});
|
|
});
|
|
|
|
it('has exactly 4 fields', () => {
|
|
expect(Object.keys(specDisplayFieldReset)).toHaveLength(4);
|
|
});
|
|
});
|