fix: memory replace/remove 归一化匹配+最低长度回退至5,修复引号差异导致删除失败

This commit is contained in:
thzxx
2026-07-10 21:47:41 +08:00
parent e5224e4a8d
commit 0145f0cfe1
2 changed files with 15 additions and 17 deletions
+14 -16
View File
@@ -530,12 +530,11 @@ export async function addEntry(
/** 替换记忆(子串匹配)
* M8: 使用写入锁串行化
* M9: 要求 oldText 至少 5 个字符,减少误匹配 */
* 要求 oldText 至少 5 个字符,减少误匹配 */
export async function replaceEntry(oldText: string, newContent: string): Promise<{ success: boolean; message: string }> {
return withWriteLock(async () => {
// M4: 提高最小匹配长度到 8,减少误匹配
if (!oldText || oldText.length < 8) {
return { success: false, message: 'old_text 不能为空且至少 8 个字符(提高精确度)' };
if (!oldText || oldText.length < 5) {
return { success: false, message: 'old_text 不能为空且至少 5 个字符(提高精确度)' };
}
if (!newContent || newContent.length < 2) {
return { success: false, message: 'new_content 不能为空且至少 2 个字符' };
@@ -547,12 +546,12 @@ export async function replaceEntry(oldText: string, newContent: string): Promise
}
const entries = await loadAllEntries();
// M9: 大小写不敏感匹配
const oldTextLower = oldText.toLowerCase();
const matches = entries.filter(e => e.content.toLowerCase().includes(oldTextLower));
// 归一化匹配:统一全角/半角标点、空白、大小写,解决引号等字符差异
const oldTextNorm = normalizeForDedup(oldText);
const matches = entries.filter(e => normalizeForDedup(e.content).includes(oldTextNorm));
if (matches.length === 0) {
return { success: false, message: `未找到包含 "${oldText.slice(0, 50)}" 的记忆` };
return { success: false, message: `未找到包含 "${oldText.slice(0, 50)}" 的记忆。建议先调用 memory read_all 查看完整内容,再用精确的 old_text 重试` };
}
if (matches.length > 1) {
return { success: false, message: `匹配到 ${matches.length} 条记忆,请使用更精确的 old_text` };
@@ -579,21 +578,20 @@ export async function replaceEntry(oldText: string, newContent: string): Promise
/** 删除记忆(子串匹配)
* M8: 使用写入锁串行化
* M4: 要求 oldText 至少 8 个字符,减少误匹配 */
* 要求 oldText 至少 5 个字符,减少误匹配 */
export async function removeEntry(oldText: string): Promise<{ success: boolean; message: string }> {
return withWriteLock(async () => {
// M4: 提高最小匹配长度到 8
if (!oldText || oldText.length < 8) {
return { success: false, message: 'old_text 不能为空且至少 8 个字符(提高精确度)' };
if (!oldText || oldText.length < 5) {
return { success: false, message: 'old_text 不能为空且至少 5 个字符(提高精确度)' };
}
const entries = await loadAllEntries();
// M9: 大小写不敏感匹配
const oldTextLower = oldText.toLowerCase();
const matches = entries.filter(e => e.content.toLowerCase().includes(oldTextLower));
// 归一化匹配:统一全角/半角标点、空白、大小写,解决引号等字符差异
const oldTextNorm = normalizeForDedup(oldText);
const matches = entries.filter(e => normalizeForDedup(e.content).includes(oldTextNorm));
if (matches.length === 0) {
return { success: false, message: `未找到包含 "${oldText.slice(0, 50)}" 的记忆` };
return { success: false, message: `未找到包含 "${oldText.slice(0, 50)}" 的记忆。建议先调用 memory read_all 查看完整内容,再用精确的 old_text 重试` };
}
if (matches.length > 1) {
return { success: false, message: `匹配到 ${matches.length} 条记忆,请使用更精确的 old_text` };
+1 -1
View File
@@ -378,7 +378,7 @@ CRITICAL: For add action, you MUST include both "type" (fact/preference/rule) an
content: { type: 'string', description: '[add REQUIRED, replace] Memory text. Keep it concise (8-100 chars).' },
importance: { type: 'integer', description: '[add] Priority 1-10. Default: 5. Use 8+ for critical info.' },
tags: { type: 'array', items: { type: 'string' }, description: '[add] 2-5 keywords for search matching.' },
old_text: { type: 'string', description: '[replace, remove REQUIRED] Unique substring to identify the entry. Must be ≥8 chars for precision.' },
old_text: { type: 'string', description: '[replace, remove REQUIRED] Unique substring to identify the entry. Must be ≥5 chars. Use exact text from read_all for best results.' },
new_content: { type: 'string', description: '[replace REQUIRED] New text to replace with.' }
}
}