LibreChat/api/server/services/Endpoints/assistants/title.test.js
Danny Avila 67b7b441b2
🛂 feat: Filter Model-Bound Content by Source (#14425)
* feat: introduce optional content protection seam

* feat: enforce source-aware content filters

* feat: complete source-aware content enforcement

* test: activate skill file-text fail-close fixtures

* fix: harden source-aware content filters

* fix: harden model-bound content filtering

* fix: preserve legacy filters and generated files

* fix: inspect shared scalar metadata

* test: align mocks with current dev dependencies

* feat: add persisted content filter safeguards

* feat: complete source-aware content filter enforcement

* fix: move resume content preflight into TypeScript

* fix: close content inspection edge cases

* fix: harden content protection boundaries

* fix: complete content protection safeguards

* test: align persisted memory filter coverage

* fix: reconcile content protection with current dev

* fix: reconcile content protection with latest dev

* fix: close content protection review gaps

* fix: enforce source-aware provider boundaries

* fix: preserve legacy PII preflight semantics

* test: stabilize stored branch preflight fixture

* fix: defer agent writes until protected model admission

* perf: harden source-aware model-bound filtering

* fix: canonicalize provider lineage before validation

* fix: satisfy model-bound callback type checks

* perf: Bound content protection filtering work

* fix: Bound submission array traversal

* fix: Stabilize bounded content snapshots

* fix: Scope model-bound traversal overflows

* fix: Preserve scoped content inspection

* fix: Accumulate aggregate traversal scopes

* fix: centralize content policy boundaries

* test: align deferred tool policy context

* test: align controller policy mocks

* style: normalize content protection imports

* fix: close content policy review gaps

* fix: narrow active skill policy config

* fix: address content protection review boundaries

* fix: retain exact provenance overflow sentinel

* fix: preserve literal and scoped provenance updates

* fix: narrow persisted edit provenance

* fix: isolate exact overflow attribution

* fix: centralize stored prompt protection

* fix: fail closed on incomplete transcript evidence

* fix: align canonical transcript routing

* refactor: centralize content policy preflights

* fix: isolate upload policy error typing

* style: sort policy preflight imports

* refactor: centralize content policy boundaries
2026-08-21 22:43:32 -04:00

110 lines
3 KiB
JavaScript

const mockCache = {
set: jest.fn(),
};
const mockSaveConvo = jest.fn();
const mockInitializeClient = jest.fn();
jest.mock('@librechat/api', () => ({
...jest.requireActual('@librechat/api'),
isEnabled: (value) => value === true || value === 'true',
sanitizeTitle: (title) => title,
}));
jest.mock('@librechat/data-schemas', () => ({
logger: { debug: jest.fn(), info: jest.fn(), warn: jest.fn(), error: jest.fn() },
}));
jest.mock('~/cache/getLogStores', () => jest.fn(() => mockCache));
jest.mock(
'./initalize',
() =>
(...args) =>
mockInitializeClient(...args),
);
jest.mock('~/models', () => ({
saveConvo: (...args) => mockSaveConvo(...args),
}));
const addTitle = require('./title');
describe('assistants addTitle content policy', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('replaces a blocked generated title before caching or saving it', async () => {
const create = jest.fn().mockResolvedValue({
choices: [{ message: { content: 'BLOCKED-GENERATED-TITLE' } }],
});
mockInitializeClient.mockResolvedValue({
openai: { chat: { completions: { create } } },
});
const req = {
user: { id: 'user-1' },
body: {},
config: {
filters: {
conversationTitles: {
pii: {
starterPatterns: [],
customPatterns: [{ id: 'blocked', label: 'blocked', regex: 'BLOCKED' }],
},
},
},
},
};
await addTitle(req, {
text: 'submitted text',
responseText: 'response',
conversationId: 'conversation-generated',
});
expect(mockCache.set).toHaveBeenCalledWith('user-1-conversation-generated', 'New Chat', 120000);
expect(mockSaveConvo).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({
conversationId: 'conversation-generated',
title: 'New Chat',
}),
expect.objectContaining({ noUpsert: true }),
);
});
it('replaces a blocked submitted-text fallback before caching or saving it', async () => {
const create = jest.fn().mockRejectedValue(new Error('title model unavailable'));
mockInitializeClient.mockResolvedValue({
openai: { chat: { completions: { create } } },
});
const req = {
user: { id: 'user-1' },
body: {},
config: {
filters: {
conversationTitles: {
pii: {
starterPatterns: [],
customPatterns: [{ id: 'blocked', label: 'blocked', regex: 'BLOCKED' }],
},
},
},
},
};
await addTitle(req, {
text: 'BLOCKED-SUBMISSION',
responseText: 'response',
conversationId: 'conversation-1',
});
expect(mockCache.set).toHaveBeenCalledWith('user-1-conversation-1', 'New Chat', 120000);
expect(mockSaveConvo).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({
conversationId: 'conversation-1',
title: 'New Chat',
}),
expect.objectContaining({ noUpsert: true }),
);
});
});