mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-06-28 02:11:30 +00:00
🧩 fix: Bring memory tool to parity with other ephemeral tools
- Add `memory` to the model-spec schema/type and honor `modelSpec.memory` in both ephemeral paths (load.ts, added.ts) and the frontend spec application, so admins can pre-enable Memory from a model spec exactly like webSearch/fileSearch/executeCode. - Add LAST_MEMORY_TOGGLE_ to the timestamped-storage cleanup list so stale per-conversation memory toggles are purged on startup like the others. - Hide the agent-builder Memory toggle for users who disabled memory in personalization (memories === false), mirroring the chat badge's opt-out gate, so the setting isn't shown as inert/misleading.
This commit is contained in:
parent
b5362e9b28
commit
672a03b052
7 changed files with 31 additions and 4 deletions
|
|
@ -20,7 +20,13 @@ import {
|
|||
getIconKey,
|
||||
cn,
|
||||
} from '~/utils';
|
||||
import { useLocalize, useVisibleTools, useHasAccess, useHasMemoryAccess } from '~/hooks';
|
||||
import {
|
||||
useLocalize,
|
||||
useVisibleTools,
|
||||
useHasAccess,
|
||||
useHasMemoryAccess,
|
||||
useAuthContext,
|
||||
} from '~/hooks';
|
||||
import { ToolSelectDialog, MCPToolSelectDialog } from '~/components/Tools';
|
||||
import useAgentCapabilities from '~/hooks/Agents/useAgentCapabilities';
|
||||
import { useListSkillsQuery, useGetAgentFiles } from '~/data-provider';
|
||||
|
|
@ -114,8 +120,12 @@ export default function AgentConfig() {
|
|||
permissionType: PermissionTypes.SKILLS,
|
||||
permission: Permissions.USE,
|
||||
});
|
||||
const { user } = useAuthContext();
|
||||
const hasMemoryAccess = useHasMemoryAccess();
|
||||
const showMemory = hasMemoryAccess && memoryEnabled;
|
||||
/** Mirror the chat memory badge's opt-out gate: a user who disabled memory in
|
||||
* personalization can't use the inline tools, so the builder toggle is inert
|
||||
* for them and must be hidden too. */
|
||||
const showMemory = hasMemoryAccess && memoryEnabled && user?.personalization?.memories !== false;
|
||||
const showSkills = hasSkillsAccess && skillsEnabled;
|
||||
const { data: skillsData } = useListSkillsQuery({ limit: 100 }, { enabled: showSkills });
|
||||
const skillsMap = useMemo(() => {
|
||||
|
|
|
|||
|
|
@ -132,6 +132,19 @@ describe('timestamps', () => {
|
|||
|
||||
expect(localStorage.getItem(regularKey)).toBe('value');
|
||||
});
|
||||
|
||||
it('should purge stale memory toggle entries', () => {
|
||||
const key = `${LocalStorageKeys.LAST_MEMORY_TOGGLE_}convo-321`;
|
||||
const oldTimestamp = Date.now() - 3 * 24 * 60 * 60 * 1000; // 3 days ago
|
||||
|
||||
localStorage.setItem(key, 'true');
|
||||
localStorage.setItem(`${key}_TIMESTAMP`, oldTimestamp.toString());
|
||||
|
||||
cleanupTimestampedStorage();
|
||||
|
||||
expect(localStorage.getItem(key)).toBeNull();
|
||||
expect(localStorage.getItem(`${key}_TIMESTAMP`)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('migrateExistingEntries', () => {
|
||||
|
|
|
|||
|
|
@ -368,6 +368,7 @@ export function applyModelSpecEphemeralAgent({
|
|||
web_search: modelSpec.webSearch ?? false,
|
||||
file_search: modelSpec.fileSearch ?? false,
|
||||
execute_code: modelSpec.executeCode ?? false,
|
||||
memory: modelSpec.memory ?? false,
|
||||
artifacts: modelSpec.artifacts === true ? 'default' : modelSpec.artifacts || '',
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ const TIMESTAMPED_KEYS = [
|
|||
LocalStorageKeys.LAST_WEB_SEARCH_TOGGLE_,
|
||||
LocalStorageKeys.LAST_FILE_SEARCH_TOGGLE_,
|
||||
LocalStorageKeys.LAST_ARTIFACTS_TOGGLE_,
|
||||
LocalStorageKeys.LAST_MEMORY_TOGGLE_,
|
||||
LocalStorageKeys.PIN_MCP_,
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ export async function loadAddedAgent(
|
|||
if (ephemeralAgent?.web_search === true || modelSpec?.webSearch === true) {
|
||||
tools.push(Tools.web_search);
|
||||
}
|
||||
if (ephemeralAgent?.memory === true) {
|
||||
if (ephemeralAgent?.memory === true || modelSpec?.memory === true) {
|
||||
tools.push(Tools.memory);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ export async function loadEphemeralAgent(
|
|||
if (ephemeralAgent?.web_search === true || modelSpec?.webSearch === true) {
|
||||
tools.push(Tools.web_search);
|
||||
}
|
||||
if (ephemeralAgent?.memory === true) {
|
||||
if (ephemeralAgent?.memory === true || modelSpec?.memory === true) {
|
||||
tools.push(Tools.memory);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ export type TModelSpec = {
|
|||
webSearch?: boolean;
|
||||
fileSearch?: boolean;
|
||||
executeCode?: boolean;
|
||||
memory?: boolean;
|
||||
artifacts?: string | boolean;
|
||||
mcpServers?: string[];
|
||||
skills?: boolean | string[];
|
||||
|
|
@ -76,6 +77,7 @@ export const tModelSpecSchema = z.object({
|
|||
webSearch: z.boolean().optional(),
|
||||
fileSearch: z.boolean().optional(),
|
||||
executeCode: z.boolean().optional(),
|
||||
memory: z.boolean().optional(),
|
||||
artifacts: z.union([z.string(), z.boolean()]).optional(),
|
||||
mcpServers: z.array(z.string()).optional(),
|
||||
skills: z.union([z.boolean(), z.array(z.string())]).optional(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue