From 3d4b4eb7c41ab09d1dcf7e1082391def10c754be Mon Sep 17 00:00:00 2001 From: Wx-2025 <351320169@qq.com> Date: Sun, 30 Nov 2025 23:02:51 +0800 Subject: [PATCH] Delete super-memory directory --- super-memory/bindings.js | 89 ------------- super-memory/index.html | 85 ------------ super-memory/lorebook-bridge.js | 228 -------------------------------- super-memory/manager.js | 203 ---------------------------- super-memory/smart-indexer.js | 77 ----------- 5 files changed, 682 deletions(-) delete mode 100644 super-memory/bindings.js delete mode 100644 super-memory/index.html delete mode 100644 super-memory/lorebook-bridge.js delete mode 100644 super-memory/manager.js delete mode 100644 super-memory/smart-indexer.js diff --git a/super-memory/bindings.js b/super-memory/bindings.js deleted file mode 100644 index 591de3f..0000000 --- a/super-memory/bindings.js +++ /dev/null @@ -1,89 +0,0 @@ -import { extensionName } from "../../utils/settings.js"; -import { extension_settings } from "/scripts/extensions.js"; -import { saveSettingsDebounced } from "/script.js"; -import { initializeSuperMemory } from "./manager.js"; - -export function bindSuperMemoryEvents() { - const panel = $('#amily2_super_memory_panel'); - if (panel.length === 0) return; - - panel.on('click', '.sm-nav-item', function() { - const tab = $(this).data('tab'); - - panel.find('.sm-nav-item').removeClass('active'); - $(this).addClass('active'); - - panel.find('.sm-tab-pane').removeClass('active'); - panel.find(`#sm-${tab}-tab`).addClass('active'); - }); - - panel.on('change', 'input[type="checkbox"]', function() { - if (!extension_settings[extensionName]) extension_settings[extensionName] = {}; - - const id = this.id; - let key = null; - - if (id === 'sm-system-enabled') key = 'super_memory_enabled'; - if (id === 'sm-bridge-enabled') key = 'superMemory_bridgeEnabled'; - - if (key) { - extension_settings[extensionName][key] = this.checked; - saveSettingsDebounced(); - console.log(`[Amily2-SuperMemory] Setting updated: ${key} = ${this.checked}`); - } - }); - - panel.on('change', 'input[type="number"], input[type="text"]', function() { - if (!extension_settings[extensionName]) extension_settings[extensionName] = {}; - - const id = this.id; - let key = null; - - if (id === 'sm-index-depth') key = 'superMemory_indexDepth'; - if (id === 'sm-detail-depth') key = 'superMemory_detailDepth'; - - if (key) { - let value = this.value; - if (this.type === 'number') value = parseInt(value, 10); - - extension_settings[extensionName][key] = value; - saveSettingsDebounced(); - console.log(`[Amily2-SuperMemory] Setting updated: ${key} = ${value}`); - } - }); - - loadSuperMemorySettings(); - - console.log('[Amily2-SuperMemory] Events bound successfully.'); -} - -function loadSuperMemorySettings() { - const settings = extension_settings[extensionName] || {}; - - $('#sm-system-enabled').prop('checked', settings.super_memory_enabled ?? false); - $('#sm-bridge-enabled').prop('checked', settings.superMemory_bridgeEnabled ?? false); - - $('#sm-index-depth').val(settings.superMemory_indexDepth ?? 0); - $('#sm-detail-depth').val(settings.superMemory_detailDepth ?? 2); -} - -window.sm_initializeSystem = async function() { - toastr.info('超级记忆系统正在初始化...'); - $('#sm-system-status').text('初始化中...').css('color', 'yellow'); - - try { - await initializeSuperMemory(); - toastr.success('超级记忆系统初始化完成。'); - } catch (error) { - console.error(error); - toastr.error('初始化失败,请检查控制台。'); - $('#sm-system-status').text('错误').css('color', 'red'); - } -}; - -window.sm_purgeMemory = function() { - if (confirm('您确定要清空所有超级记忆数据吗?')) { - toastr.warning('记忆已清空。'); - $('#sm-system-status').text('未初始化').css('color', '#ffc107'); - } -}; diff --git a/super-memory/index.html b/super-memory/index.html deleted file mode 100644 index dcb5240..0000000 --- a/super-memory/index.html +++ /dev/null @@ -1,85 +0,0 @@ -
-
- 灵台 · 记忆中枢 -
- -
-
- -
-
-

究极长期记忆 (Super Memory)

-

欢迎来到 Amily2 的核心记忆中枢。这里掌管着世界的记忆,连接着每一个角色、每一个物品与每一段传说。

-

通过“三级金字塔”注入策略,我们将实现极致的 Token 节省与无限的记忆深度。

-
- -
- - - -
- -
- -
-
- 状态监控 -
- - 未初始化 -
-
- - 0 条目 -
-
- - 0 条目 -
-
- - -
-
-
- - -
-
- 记忆策略配置 -
- - -
-
- - -
-
- - -
-
- - -
-
-
- - -
-
- 关联网络 (The Mesh) -

关联触发逻辑正在开发中...

-
-
-
-
diff --git a/super-memory/lorebook-bridge.js b/super-memory/lorebook-bridge.js deleted file mode 100644 index dfdcfcf..0000000 --- a/super-memory/lorebook-bridge.js +++ /dev/null @@ -1,228 +0,0 @@ -import { amilyHelper } from "../tavern-helper/main.js"; -import { extension_settings, getContext } from "/scripts/extensions.js"; -import { extensionName } from "../../utils/settings.js"; -import { this_chid, characters } from "/script.js"; - -function getMemoryBookName() { - let charName = "Global"; - const context = getContext(); - - if (this_chid !== undefined && characters[this_chid]) { - charName = characters[this_chid].name; - } else if (context.characterId !== undefined && characters[context.characterId]) { - charName = characters[context.characterId].name; - } - - const safeCharName = charName.replace(/[<>:"/\\|?*]/g, '_'); - return `Amily2_Memory_${safeCharName}`; -} - -export async function syncToLorebook(tableName, data, indexText, role, headers, rowStatuses, depth = 100) { - console.log(`[Amily2-Bridge] 开始同步表格: ${tableName} (Depth: ${depth})`); - - await ensureMemoryBook(); - - const bookName = getMemoryBookName(); - - let entries = await amilyHelper.getLorebookEntries(bookName); - if (!entries) entries = []; - - const entriesToUpdate = []; - const entriesToCreate = []; - - const processEntry = (comment, keys, content, type = 'selective', enabled = true) => { - const existingEntry = entries.find(e => e.comment === comment); - if (existingEntry) { - existingEntry.content = content; - existingEntry.key = keys; - existingEntry.order = depth; - - if (type === 'constant') { - existingEntry.constant = true; - } else { - existingEntry.constant = false; - } - if (existingEntry.enabled !== undefined) { - existingEntry.enabled = enabled; - } else { - existingEntry.disable = !enabled; - } - entriesToUpdate.push(existingEntry); - } else { - entriesToCreate.push({ - comment: comment, - keys: keys, - content: content, - type: type, - position: 1, - order: depth, - enabled: enabled - }); - } - }; - - if (role === 'database') { - const indexKey = [`Amily_Index_${tableName}`]; - const indexComment = `[Amily2] Index for ${tableName}`; - let indexContent = `【${tableName} 索引】\n${indexText.trim()}`; - - if (tableName.includes("大纲")) { - indexContent += `\n\n【Amily2-前瞻性预测指令】\n为了实现“提前一轮触发绿灯世界书”的高级记忆回流,请在生成本轮回复时,根据当前剧情走向,**大胆预测并自然提及**下一轮可能出现的索引编码。可自行增加一个标签并使用html注释掉该编码。这将激活系统的预加载机制,确保剧情发展的连贯性。\n`; - } - - processEntry(indexComment, indexKey, indexContent, 'constant'); - } - - data.forEach((row, index) => { - if (!row || row.length === 0) return; - - const primaryVal = row[0]; - - if (!primaryVal) return; - - const isPendingDeletion = rowStatuses && rowStatuses[index] === 'pending-deletion'; - const isEnabled = !isPendingDeletion; - - const triggerKeys = [primaryVal]; - const entryComment = `[Amily2] Detail: ${tableName} - ${primaryVal}`; - - let finalHeaders = headers; - if (!finalHeaders || finalHeaders.length < row.length) { - finalHeaders = []; - for(let i=0; i 0) { - console.log(`[Amily2-Bridge] 清理 ${entriesToDelete.length} 个废弃条目...`); - await amilyHelper.deleteLorebookEntries(bookName, entriesToDelete); - } - - if (entriesToUpdate.length > 0) { - console.log(`[Amily2-Bridge] 更新 ${entriesToUpdate.length} 个条目...`); - await amilyHelper.setLorebookEntries(bookName, entriesToUpdate); - } - - if (entriesToCreate.length > 0) { - console.log(`[Amily2-Bridge] 创建 ${entriesToCreate.length} 个新条目...`); - await amilyHelper.createLorebookEntries(bookName, entriesToCreate); - } - console.log(`[Amily2-Bridge] 同步完成: ${tableName}`); -} - -export async function ensureMemoryBook() { - const bookName = getMemoryBookName(); - const books = await amilyHelper.getLorebooks(); - - if (!books.includes(bookName)) { - console.log(`[Amily2-Bridge] 创建角色专用世界书: ${bookName}`); - await amilyHelper.createLorebook(bookName); - } - - const settings = extension_settings[extensionName] || {}; - const shouldBind = settings.superMemory_autoBind === true; - - if (shouldBind && bookName.startsWith("Amily2_Memory_") && bookName !== "Amily2_Memory_Global") { - console.log(`[Amily2-Bridge] 自动绑定世界书到当前角色...`); - await amilyHelper.bindLorebookToCharacter(bookName); - } else if (!shouldBind) { - console.log(`[Amily2-Bridge] 跳过自动绑定 (设置已禁用)。请手动在世界书管理中激活: ${bookName}`); - } -} - -function createEntryTemplate() { - return { - uid: Date.now() + Math.floor(Math.random() * 1000), - key: [], - keysecondary: [], - comment: "", - content: "", - constant: false, - selective: true, - order: 100, - position: 1, - enabled: true - }; -} - -export async function updateTransientHint(hint) { - console.log('[Amily2-Bridge] 更新瞬时记忆提示...'); - await ensureMemoryBook(); - const bookName = getMemoryBookName(); - - const comment = "[Amily2] Active Memory Hint"; - const content = hint ? `\n\n【重要记忆回响】\n${hint}\n\n` : ""; - const enabled = !!hint; - - let entries = await amilyHelper.getLorebookEntries(bookName); - if (!entries) entries = []; - - const existingEntry = entries.find(e => e.comment === comment); - - if (existingEntry) { - existingEntry.content = content; - existingEntry.enabled = enabled; - existingEntry.order = 0; - existingEntry.constant = true; - - await amilyHelper.setLorebookEntries(bookName, [existingEntry]); - } else if (hint) { - const newEntry = { - comment: comment, - keys: [], - content: content, - constant: true, - selective: false, - order: 0, - position: 0, - enabled: true - }; - await amilyHelper.createLorebookEntries(bookName, [newEntry]); - } - - console.log(`[Amily2-Bridge] 瞬时记忆提示已${enabled ? '启用' : '清除'}。`); -} diff --git a/super-memory/manager.js b/super-memory/manager.js deleted file mode 100644 index 38f633d..0000000 --- a/super-memory/manager.js +++ /dev/null @@ -1,203 +0,0 @@ -import { extension_settings, getContext } from "/scripts/extensions.js"; -import { extensionName } from "../../utils/settings.js"; -import { amilyHelper } from "../tavern-helper/main.js"; -import { generateIndex } from "./smart-indexer.js"; -import { syncToLorebook, ensureMemoryBook, updateTransientHint } from "./lorebook-bridge.js"; -import { getMemoryState, loadMemoryState, saveMemoryState } from "../table-system/manager.js"; -import { eventSource, event_types } from "/script.js"; - -let isInitialized = false; -let updateQueue = []; -let isProcessing = false; -let lastChatId = null; - -const METADATA_KEY = 'Amily2_Memory_Data'; - -export async function initializeSuperMemory() { - const settings = extension_settings[extensionName] || {}; - if (settings.super_memory_enabled === false) { - console.log('[Amily2-SuperMemory] 功能已禁用 (super_memory_enabled = false)。'); - if (window.$) $('#sm-system-status').text('已禁用').css('color', 'gray'); - return; - } - - if (isInitialized) return; - console.log('[Amily2-SuperMemory] 初始化核心管理器...'); - - if (!amilyHelper) { - console.error('[Amily2-SuperMemory] 致命错误:AmilyHelper 未就绪。'); - return; - } - - document.addEventListener('AMILY2_TABLE_UPDATED', handleTableUpdate); - - eventSource.on(event_types.CHAT_CHANGED, async () => { - const settings = extension_settings[extensionName] || {}; - if (settings.super_memory_enabled === false) return; - - console.log('[Amily2-SuperMemory] 检测到聊天切换,正在刷新记忆状态...'); - await checkWorldBookStatus(); - - await tryRestoreStateFromMetadata(); - - await forceSyncAll(); - }); - - await checkWorldBookStatus(); - - await tryRestoreStateFromMetadata(); - - await forceSyncAll(); - - isInitialized = true; - console.log('[Amily2-SuperMemory] 核心管理器初始化完成。'); - - if (window.$) { - $('#sm-system-status').text('运行中').css('color', '#4caf50'); - } -} - -async function checkWorldBookStatus() { - try { - await ensureMemoryBook(); - } catch (error) { - console.error('[Amily2-SuperMemory] 检查世界书状态失败:', error); - } -} - -function handleTableUpdate(event) { - const settings = extension_settings[extensionName] || {}; - if (settings.super_memory_enabled === false) return; - - const { tableName, data, role, hint, headers, rowStatuses } = event.detail; - console.log(`[Amily2-SuperMemory] 检测到表格更新: ${tableName} (Role: ${role})`); - - updateQueue.push({ tableName, data, role, hint, headers, rowStatuses }); - processQueue(); -} - -async function processQueue() { - if (isProcessing || updateQueue.length === 0) return; - isProcessing = true; - - try { - while (updateQueue.length > 0) { - const task = updateQueue.shift(); - await processUpdateTask(task); - } - - await saveStateToMetadata(); - - } catch (error) { - console.error('[Amily2-SuperMemory] 处理更新队列失败:', error); - } finally { - isProcessing = false; - } -} - -async function processUpdateTask(task) { - const { tableName, data, role, hint, headers, rowStatuses } = task; - - const activeData = data.filter((_, i) => !rowStatuses || rowStatuses[i] !== 'pending-deletion'); - const indexText = generateIndex(activeData, role, tableName); - - const allTables = getMemoryState(); - const tableIndex = allTables.findIndex(t => t.name === tableName); - const depth = 8001 + (tableIndex >= 0 ? tableIndex : 99); - - await syncToLorebook(tableName, data, indexText, role, headers, rowStatuses, depth); - - if (hint) { - console.log(`[Amily2-SuperMemory] 应用主动记忆提示: ${hint}`); - await updateTransientHint(hint); - } - - console.log(`[Amily2-SuperMemory] 任务完成: ${tableName}`); - - updateDashboardCounters(); -} - -async function saveStateToMetadata() { - const context = getContext(); - if (!context.chat || context.chat.length === 0) return; - - const lastMsgIndex = context.chat.length - 1; - const lastMsg = context.chat[lastMsgIndex]; - - const currentState = getMemoryState(); - - if (!lastMsg.metadata) lastMsg.metadata = {}; - - lastMsg.metadata[METADATA_KEY] = JSON.parse(JSON.stringify(currentState)); - - if (context.saveChat) { - await context.saveChat(); - } - - console.log(`[Amily2-SuperMemory] 状态已保存至消息 #${lastMsgIndex}`); -} - -export async function tryRestoreStateFromMetadata() { - const context = getContext(); - if (!context.chat || context.chat.length === 0) return; - - let foundState = null; - let foundIndex = -1; - - for (let i = context.chat.length - 1; i >= 0; i--) { - const msg = context.chat[i]; - if (msg.metadata && msg.metadata[METADATA_KEY]) { - foundState = msg.metadata[METADATA_KEY]; - foundIndex = i; - break; - } - } - - if (foundState) { - console.log(`[Amily2-SuperMemory] 发现历史状态 (Msg #${foundIndex}),正在恢复...`); - if (typeof loadMemoryState === 'function') { - loadMemoryState(foundState); - await forceSyncAll(); - } else { - console.warn('[Amily2-SuperMemory] table-system 缺少 loadMemoryState 方法,无法恢复状态。'); - } - } else { - console.log('[Amily2-SuperMemory] 未在聊天记录中发现历史状态,使用默认/当前状态。'); - } -} - -function updateDashboardCounters() { - const tables = getMemoryState(); - if (tables && window.$) { - $('#sm-index-count').text(`${tables.length} 个索引`); - const totalRows = tables.reduce((acc, t) => acc + (t.rows ? t.rows.length : 0), 0); - $('#sm-detail-count').text(`${totalRows} 个详情`); - } -} - -export async function forceSyncAll() { - console.log('[Amily2-SuperMemory] 正在执行全量同步...'); - const tables = getMemoryState(); - - if (!tables || tables.length === 0) { - console.warn('[Amily2-SuperMemory] 没有可同步的表格数据。'); - return; - } - - for (const table of tables) { - let role = 'database'; - if (table.name.includes('时空') || table.name.includes('世界钟')) role = 'anchor'; - if (table.name.includes('日志') || table.name.includes('Log')) role = 'log'; - - updateQueue.push({ - tableName: table.name, - data: table.rows, - headers: table.headers, - rowStatuses: table.rowStatuses || [], - role: role - }); - } - - await processQueue(); - console.log('[Amily2-SuperMemory] 全量同步完成。'); -} diff --git a/super-memory/smart-indexer.js b/super-memory/smart-indexer.js deleted file mode 100644 index 57cd6a7..0000000 --- a/super-memory/smart-indexer.js +++ /dev/null @@ -1,77 +0,0 @@ -export function generateIndex(data, role, tableName = "") { - if (!Array.isArray(data) || data.length === 0) { - return ""; - } - - const headers = Object.keys(data[0]); - if (headers.length === 0) return ""; - - const indexColumns = identifyIndexColumns(data, headers); - - let indexLines = []; - indexLines.push(`| ${indexColumns.join(' | ')} |`); - indexLines.push(`| ${indexColumns.map(() => '---').join(' | ')} |`); - - let processedData = [...data]; - - const firstColKey = headers[0]; - const firstColVal = data[0] ? data[0][firstColKey] : ''; - const isIndexCol = (firstColKey && (firstColKey.includes('索引') || firstColKey.includes('Index'))) || - (typeof firstColVal === 'string' && /^\s*M\d+/.test(firstColVal)) || - (tableName && (tableName.includes('总结') || tableName.includes('大纲'))); - - if (isIndexCol) { - processedData.sort((a, b) => { - const valA = String(a[firstColKey] || ''); - const valB = String(b[firstColKey] || ''); - return valA.localeCompare(valB, undefined, { numeric: true }); - }); - } - - for (const row of processedData) { - const lineParts = indexColumns.map(col => { - let val = row[col]; - if (val === undefined || val === null) return ""; - val = String(val).trim(); - if (val.length > 15) val = val.substring(0, 12) + "..."; - return val; - }); - indexLines.push(`| ${lineParts.join(' | ')} |`); - } - - return indexLines.join('\n'); -} - -function identifyIndexColumns(data, headers) { - if (headers.length <= 2) return headers; - - const candidates = []; - const maxColumns = 3; - - for (const header of headers) { - if (candidates.length >= maxColumns) break; - - let totalLen = 0; - let count = 0; - for (const row of data) { - if (row[header]) { - totalLen += String(row[header]).length; - count++; - } - } - const avgLen = count > 0 ? totalLen / count : 0; - - const isLongText = avgLen > 20; - const isBlacklisted = /desc|bio|detail|history|经历|描述|详情/i.test(header); - - if (!isLongText && !isBlacklisted) { - candidates.push(header); - } - } - - if (candidates.length === 0) { - return headers.slice(0, Math.min(headers.length, maxColumns)); - } - - return candidates; -}