mirror of
https://github.com/Wx-2025/ST-Amily2-Chat-Optimisation.git
synced 2026-06-18 11:45:51 +00:00
release: v2.2.8 [2026-06-16 15:53:20]
### 新功能 - **填表记录 · 版本恢复**(填表设置面板「回退重填」旁新增「填表记录」按钮):针对"模型填表前把整张表删空 / 误删大量内容"的反馈,提供一键找回。 - **零新存储**:直接复用各楼层 `extra.amily2_tables_data` 里逐轮继承的表格快照——历史本就在聊天中,无需另建存储或元数据 - 点开列出所有带快照的楼层(最新在上),可**展开预览**每一版的表格内容(CSV)后再决定 - **恢复某版本**:把该楼层快照设为当前状态,并清除其**之后**所有楼层的快照与填表标记 hash——使该版本成为最新有效状态,后续楼层下轮自动重填会从恢复点往前重建(赌模型不再抽风) - 「回退重填」按钮保留,但版本恢复是更安全的找回路径 ### 重构 - 抽出 `_normalizeTableState` 共用旧存档字段归一逻辑,`loadTables` 与"恢复快照"复用,消除重复 ---
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
||||
import { extensionName } from "../../utils/settings.js";
|
||||
import { extension_settings } from "/scripts/extensions.js";
|
||||
import { saveSettingsDebounced } from "/script.js";
|
||||
import { saveSettingsDebounced, eventSource, event_types } from "/script.js";
|
||||
import { initializeSuperMemory, purgeSuperMemory, forceSyncAll } from "./manager.js";
|
||||
import { defaultSettings as ragDefaultSettings } from "../rag-settings.js";
|
||||
import { getMemoryState } from "../table-system/manager.js";
|
||||
@@ -131,10 +131,29 @@ export function bindSuperMemoryEvents() {
|
||||
});
|
||||
|
||||
loadSuperMemorySettings();
|
||||
|
||||
|
||||
// 切聊天后面板内容刷新:面板的表格列表只在挂载时渲染一次、之后仅靠手动「刷新表格列表」按钮,
|
||||
// 无 CHAT_CHANGED 监听 → 切换同卡不同聊天后列表停在旧聊天。这里补上:
|
||||
// 仅当面板可见时刷新;延后到表格系统的 loadTables(index.js 中 CHAT_CHANGED 后 100ms)之后,
|
||||
// 否则会渲染出尚未更新的旧 state(同 super-memory 同步那处规避的竞态)。
|
||||
eventSource.on(event_types.CHAT_CHANGED, () => {
|
||||
if (!panel.is(':visible')) return;
|
||||
setTimeout(refreshSuperMemoryPanel, 300);
|
||||
});
|
||||
|
||||
console.log('[Amily2-SuperMemory] Events bound successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新超级记忆面板的动态内容(表格列表)。供「打开面板」与「切聊天」复用。
|
||||
* 仅重渲染随聊天变化的部分;全局开关/阈值等设置不随聊天变,无需重读。
|
||||
*/
|
||||
export function refreshSuperMemoryPanel() {
|
||||
const panel = $('#amily2_super_memory_panel');
|
||||
if (panel.length === 0) return;
|
||||
renderTableSettingsList();
|
||||
}
|
||||
|
||||
function renderTableSettingsList() {
|
||||
const container = $('#sm-table-settings-list');
|
||||
container.html('<div style="text-align: center; color: #888; padding: 20px;">正在加载...</div>');
|
||||
|
||||
@@ -141,6 +141,11 @@ export function getMemoryState() {
|
||||
return getState();
|
||||
}
|
||||
|
||||
// 【死代码·保留标注】loadMemoryState / saveMemoryState 原为 super-memory 的 metadata
|
||||
// 状态恢复链路服务(saveStateToMetadata / tryRestoreStateFromMetadata)。该链路在
|
||||
// v2.2.7(commit 62b37f2)确认为死代码后停用——msg.metadata 非 ST 持久化字段,
|
||||
// 写入即蒸发。这两个函数随之无调用方(唯一引用在 super-memory/manager.js 已注释段内)。
|
||||
// 属原作者代码体系,功能本身正确无副作用,按惯例保留并标注,待确认无后续用途再清。
|
||||
export function loadMemoryState(state) {
|
||||
if (!state) return;
|
||||
setState(state);
|
||||
@@ -264,6 +269,37 @@ function getDefaultTables() {
|
||||
|
||||
// ── 加载 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* 表格状态字段兼容性归一(loadTables 与 恢复快照 共用)。
|
||||
* 旧存档可能缺 note / rule_* / charLimitRules / rowStatuses 等字段,统一补齐。
|
||||
* @param {Array} state TableState(会被原地修改并返回)
|
||||
*/
|
||||
function _normalizeTableState(state) {
|
||||
state.forEach(table => {
|
||||
if (table.note === undefined) table.note = '无';
|
||||
if (table.rule_add === undefined) table.rule_add = '允许';
|
||||
if (table.rule_delete === undefined) table.rule_delete = '允许';
|
||||
if (table.rule_update === undefined) table.rule_update = '允许';
|
||||
|
||||
// 多列规则兼容
|
||||
if (table.charLimitRule && !table.charLimitRules) {
|
||||
table.charLimitRules = {};
|
||||
if (table.charLimitRule.columnIndex !== -1 && table.charLimitRule.limit > 0) {
|
||||
table.charLimitRules[table.charLimitRule.columnIndex] = table.charLimitRule.limit;
|
||||
}
|
||||
}
|
||||
delete table.charLimitRule;
|
||||
|
||||
if (table.rowLimitRule === undefined) table.rowLimitRule = 0;
|
||||
if (table.columnWidths === undefined) table.columnWidths = [];
|
||||
|
||||
if (!table.rowStatuses) {
|
||||
table.rowStatuses = Array(table.rows.length).fill('normal');
|
||||
}
|
||||
});
|
||||
return state;
|
||||
}
|
||||
|
||||
export function loadTables(stopIndex = -1) {
|
||||
const context = getContext();
|
||||
|
||||
@@ -274,30 +310,7 @@ export function loadTables(stopIndex = -1) {
|
||||
const message = context.chat[i];
|
||||
if (message.extra && message.extra[TABLE_DATA_KEY]) {
|
||||
log(`在第 ${i} 条消息中找到基准表格数据。`, 'info');
|
||||
let loadedState = JSON.parse(JSON.stringify(message.extra[TABLE_DATA_KEY]));
|
||||
|
||||
loadedState.forEach(table => {
|
||||
if (table.note === undefined) table.note = '无';
|
||||
if (table.rule_add === undefined) table.rule_add = '允许';
|
||||
if (table.rule_delete === undefined) table.rule_delete = '允许';
|
||||
if (table.rule_update === undefined) table.rule_update = '允许';
|
||||
|
||||
// 多列规则兼容
|
||||
if (table.charLimitRule && !table.charLimitRules) {
|
||||
table.charLimitRules = {};
|
||||
if (table.charLimitRule.columnIndex !== -1 && table.charLimitRule.limit > 0) {
|
||||
table.charLimitRules[table.charLimitRule.columnIndex] = table.charLimitRule.limit;
|
||||
}
|
||||
}
|
||||
delete table.charLimitRule;
|
||||
|
||||
if (table.rowLimitRule === undefined) table.rowLimitRule = 0;
|
||||
if (table.columnWidths === undefined) table.columnWidths = [];
|
||||
|
||||
if (!table.rowStatuses) {
|
||||
table.rowStatuses = Array(table.rows.length).fill('normal');
|
||||
}
|
||||
});
|
||||
const loadedState = _normalizeTableState(JSON.parse(JSON.stringify(message.extra[TABLE_DATA_KEY])));
|
||||
|
||||
setState(loadedState);
|
||||
dispatchAllTablesUpdate();
|
||||
@@ -597,6 +610,79 @@ export async function rollbackAndRefill() {
|
||||
}
|
||||
}
|
||||
|
||||
// ── 填表记录(版本恢复) ────────────────────────────────────────────────────
|
||||
// 复用各楼层 extra 里逐轮继承的 amily2_tables_data 快照,无需新建存储。
|
||||
|
||||
const PROCESS_HASH_KEY = 'amily2_process_hash';
|
||||
|
||||
/**
|
||||
* 列出当前聊天里所有带表格快照的楼层(升序,最旧→最新)。
|
||||
* @returns {Array<{index:number, isUser:boolean, preview:string, tableCount:number, rowCount:number}>}
|
||||
*/
|
||||
export function listFillSnapshots() {
|
||||
const context = getContext();
|
||||
if (!context || !context.chat) return [];
|
||||
const result = [];
|
||||
context.chat.forEach((msg, index) => {
|
||||
const snap = msg.extra?.[TABLE_DATA_KEY];
|
||||
if (snap && Array.isArray(snap)) {
|
||||
const rowCount = snap.reduce((acc, t) => acc + (t.rows?.length || 0), 0);
|
||||
result.push({
|
||||
index,
|
||||
isUser: !!msg.is_user,
|
||||
preview: (msg.mes || '').replace(/\s+/g, ' ').slice(0, 30),
|
||||
tableCount: snap.length,
|
||||
rowCount,
|
||||
});
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/** 把指定楼层的快照渲染成 CSV 文本(供预览)。 */
|
||||
export function getSnapshotCsv(floorIndex) {
|
||||
const context = getContext();
|
||||
const snap = context?.chat?.[floorIndex]?.extra?.[TABLE_DATA_KEY];
|
||||
if (!snap) return '';
|
||||
return tablesToCsv(_normalizeTableState(JSON.parse(JSON.stringify(snap))));
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复到指定楼层的表格快照:把该快照设为当前状态,并清除其**之后**所有楼层的
|
||||
* 快照与填表标记 hash——让该楼层成为最新有效状态,其后楼层无 hash → 下轮自动
|
||||
* 重填会从恢复点往前重建。用于救回"模型把表删空"等场景。
|
||||
* @param {number} floorIndex
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
export async function restoreToSnapshot(floorIndex) {
|
||||
const context = getContext();
|
||||
if (!context || !context.chat) return false;
|
||||
const snap = context.chat[floorIndex]?.extra?.[TABLE_DATA_KEY];
|
||||
if (!snap) {
|
||||
toastr.error('该楼层没有可恢复的表格快照。');
|
||||
return false;
|
||||
}
|
||||
|
||||
const restored = _normalizeTableState(JSON.parse(JSON.stringify(snap)));
|
||||
setState(restored);
|
||||
|
||||
// 从 floorIndex+1 起,清掉所有更新楼层的快照与 hash
|
||||
let clearedSnap = 0;
|
||||
for (let i = floorIndex + 1; i < context.chat.length; i++) {
|
||||
const e = context.chat[i].extra;
|
||||
if (!e) continue;
|
||||
if (e[TABLE_DATA_KEY] !== undefined) { delete e[TABLE_DATA_KEY]; clearedSnap++; }
|
||||
if (e[PROCESS_HASH_KEY] !== undefined) delete e[PROCESS_HASH_KEY];
|
||||
}
|
||||
|
||||
await saveChat();
|
||||
dispatchAllTablesUpdate();
|
||||
renderTables();
|
||||
updateOrInsertTableInChat();
|
||||
log(`已恢复到第 ${floorIndex + 1} 楼的表格快照,清理其后 ${clearedSnap} 条快照与填表标记。`, 'success');
|
||||
return true;
|
||||
}
|
||||
|
||||
// ── 杂项 ──────────────────────────────────────────────────────────────────
|
||||
|
||||
export function isCurrentTablesEmpty() {
|
||||
|
||||
Reference in New Issue
Block a user