mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-16 16:30:15 +01:00
🐛 fix: Memories Key Updates (#8302)
* Updated the PATCH /memories/:key endpoint to allow key changes while ensuring no duplicate keys exist. * Improved error handling in MemoryCreateDialog and MemoryEditDialog for key validation and duplication scenarios. * Added a new translation for memory key validation error in translation.json.
This commit is contained in:
parent
f4d97e1672
commit
12b08183ff
4 changed files with 68 additions and 15 deletions
|
|
@ -172,40 +172,68 @@ router.patch('/preferences', checkMemoryOptOut, async (req, res) => {
|
|||
/**
|
||||
* PATCH /memories/:key
|
||||
* Updates the value of an existing memory entry for the authenticated user.
|
||||
* Body: { value: string }
|
||||
* Body: { key?: string, value: string }
|
||||
* Returns 200 and { updated: true, memory: <updatedDoc> } when successful.
|
||||
*/
|
||||
router.patch('/:key', checkMemoryUpdate, async (req, res) => {
|
||||
const { key } = req.params;
|
||||
const { value } = req.body || {};
|
||||
const { key: urlKey } = req.params;
|
||||
const { key: bodyKey, value } = req.body || {};
|
||||
|
||||
if (typeof value !== 'string' || value.trim() === '') {
|
||||
return res.status(400).json({ error: 'Value is required and must be a non-empty string.' });
|
||||
}
|
||||
|
||||
// Use the key from the body if provided, otherwise use the key from the URL
|
||||
const newKey = bodyKey || urlKey;
|
||||
|
||||
try {
|
||||
const tokenCount = Tokenizer.getTokenCount(value, 'o200k_base');
|
||||
|
||||
const memories = await getAllUserMemories(req.user.id);
|
||||
const existingMemory = memories.find((m) => m.key === key);
|
||||
const existingMemory = memories.find((m) => m.key === urlKey);
|
||||
|
||||
if (!existingMemory) {
|
||||
return res.status(404).json({ error: 'Memory not found.' });
|
||||
}
|
||||
|
||||
const result = await setMemory({
|
||||
userId: req.user.id,
|
||||
key,
|
||||
value,
|
||||
tokenCount,
|
||||
});
|
||||
// If the key is changing, we need to handle it specially
|
||||
if (newKey !== urlKey) {
|
||||
const keyExists = memories.find((m) => m.key === newKey);
|
||||
if (keyExists) {
|
||||
return res.status(409).json({ error: 'Memory with this key already exists.' });
|
||||
}
|
||||
|
||||
if (!result.ok) {
|
||||
return res.status(500).json({ error: 'Failed to update memory.' });
|
||||
const createResult = await createMemory({
|
||||
userId: req.user.id,
|
||||
key: newKey,
|
||||
value,
|
||||
tokenCount,
|
||||
});
|
||||
|
||||
if (!createResult.ok) {
|
||||
return res.status(500).json({ error: 'Failed to create new memory.' });
|
||||
}
|
||||
|
||||
const deleteResult = await deleteMemory({ userId: req.user.id, key: urlKey });
|
||||
if (!deleteResult.ok) {
|
||||
return res.status(500).json({ error: 'Failed to delete old memory.' });
|
||||
}
|
||||
} else {
|
||||
// Key is not changing, just update the value
|
||||
const result = await setMemory({
|
||||
userId: req.user.id,
|
||||
key: newKey,
|
||||
value,
|
||||
tokenCount,
|
||||
});
|
||||
|
||||
if (!result.ok) {
|
||||
return res.status(500).json({ error: 'Failed to update memory.' });
|
||||
}
|
||||
}
|
||||
|
||||
const updatedMemories = await getAllUserMemories(req.user.id);
|
||||
const updatedMemory = updatedMemories.find((m) => m.key === key);
|
||||
const updatedMemory = updatedMemories.find((m) => m.key === newKey);
|
||||
|
||||
res.json({ updated: true, memory: updatedMemory });
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -52,6 +52,10 @@ export default function MemoryCreateDialog({
|
|||
if (axiosError.response?.status === 409 || errorMessage.includes('already exists')) {
|
||||
errorMessage = localize('com_ui_memory_key_exists');
|
||||
}
|
||||
// Check for key validation error (lowercase and underscores only)
|
||||
else if (errorMessage.includes('lowercase letters and underscores')) {
|
||||
errorMessage = localize('com_ui_memory_key_validation');
|
||||
}
|
||||
}
|
||||
} else if (error.message) {
|
||||
errorMessage = error.message;
|
||||
|
|
|
|||
|
|
@ -44,9 +44,29 @@ export default function MemoryEditDialog({
|
|||
status: 'success',
|
||||
});
|
||||
},
|
||||
onError: () => {
|
||||
onError: (error: Error) => {
|
||||
let errorMessage = localize('com_ui_error');
|
||||
|
||||
if (error && typeof error === 'object' && 'response' in error) {
|
||||
const axiosError = error as any;
|
||||
if (axiosError.response?.data?.error) {
|
||||
errorMessage = axiosError.response.data.error;
|
||||
|
||||
// Check for duplicate key error
|
||||
if (axiosError.response?.status === 409 || errorMessage.includes('already exists')) {
|
||||
errorMessage = localize('com_ui_memory_key_exists');
|
||||
}
|
||||
// Check for key validation error (lowercase and underscores only)
|
||||
else if (errorMessage.includes('lowercase letters and underscores')) {
|
||||
errorMessage = localize('com_ui_memory_key_validation');
|
||||
}
|
||||
}
|
||||
} else if (error.message) {
|
||||
errorMessage = error.message;
|
||||
}
|
||||
|
||||
showToast({
|
||||
message: localize('com_ui_error'),
|
||||
message: errorMessage,
|
||||
status: 'error',
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -856,6 +856,7 @@
|
|||
"com_ui_memory_deleted": "Memory deleted",
|
||||
"com_ui_memory_deleted_items": "Deleted Memories",
|
||||
"com_ui_memory_key_exists": "A memory with this key already exists. Please use a different key.",
|
||||
"com_ui_memory_key_validation": "Memory key must only contain lowercase letters and underscores.",
|
||||
"com_ui_memory_updated": "Updated saved memory",
|
||||
"com_ui_memory_updated_items": "Updated Memories",
|
||||
"com_ui_mention": "Mention an endpoint, assistant, or preset to quickly switch to it",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue