release: v2.2.8 [2026-06-16 15:53:20]

### 新功能
- **填表记录 · 版本恢复**(填表设置面板「回退重填」旁新增「填表记录」按钮):针对"模型填表前把整张表删空 / 误删大量内容"的反馈,提供一键找回。
  - **零新存储**:直接复用各楼层 `extra.amily2_tables_data` 里逐轮继承的表格快照——历史本就在聊天中,无需另建存储或元数据
  - 点开列出所有带快照的楼层(最新在上),可**展开预览**每一版的表格内容(CSV)后再决定
  - **恢复某版本**:把该楼层快照设为当前状态,并清除其**之后**所有楼层的快照与填表标记 hash——使该版本成为最新有效状态,后续楼层下轮自动重填会从恢复点往前重建(赌模型不再抽风)
  - 「回退重填」按钮保留,但版本恢复是更安全的找回路径
### 重构
- 抽出 `_normalizeTableState` 共用旧存档字段归一逻辑,`loadTables` 与"恢复快照"复用,消除重复
---
This commit is contained in:
Jenkins CI
2026-06-16 15:53:20 +08:00
parent cc6618a493
commit 4b2229f0f4
14 changed files with 213 additions and 329 deletions

View File

@@ -95,6 +95,22 @@
---
## v2.2.8
### 新功能
- **填表记录 · 版本恢复**(填表设置面板「回退重填」旁新增「填表记录」按钮):针对"模型填表前把整张表删空 / 误删大量内容"的反馈,提供一键找回。
- **零新存储**:直接复用各楼层 `extra.amily2_tables_data` 里逐轮继承的表格快照——历史本就在聊天中,无需另建存储或元数据
- 点开列出所有带快照的楼层(最新在上),可**展开预览**每一版的表格内容CSV后再决定
- **恢复某版本**:把该楼层快照设为当前状态,并清除其**之后**所有楼层的快照与填表标记 hash——使该版本成为最新有效状态后续楼层下轮自动重填会从恢复点往前重建赌模型不再抽风
- 「回退重填」按钮保留,但版本恢复是更安全的找回路径
### 重构
- 抽出 `_normalizeTableState` 共用旧存档字段归一逻辑,`loadTables` 与"恢复快照"复用,消除重复
---
## v2.2.7
### 修复

View File

@@ -439,6 +439,7 @@
<button id="fill-selected-floors-btn" class="menu_button accent small_button">选定楼层填表</button>
<button id="fill-current-floor-btn" class="menu_button secondary small_button">填当前楼层</button>
<button id="rollback-and-refill-btn" class="menu_button secondary small_button">回退重填</button>
<button id="table-fill-history-btn" class="menu_button secondary small_button" title="浏览各楼层保存的表格快照,可恢复到任意版本(救回被模型清空的表格)">填表记录</button>
<button id="reorganize-table-btn" class="menu_button warning small_button">重新整理</button>
</div>
</div>

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

View File

@@ -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";
@@ -132,9 +132,28 @@ export function bindSuperMemoryEvents() {
loadSuperMemorySettings();
// 切聊天后面板内容刷新:面板的表格列表只在挂载时渲染一次、之后仅靠手动「刷新表格列表」按钮,
// 无 CHAT_CHANGED 监听 → 切换同卡不同聊天后列表停在旧聊天。这里补上:
// 仅当面板可见时刷新;延后到表格系统的 loadTablesindex.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>');

View File

@@ -141,6 +141,11 @@ export function getMemoryState() {
return getState();
}
// 【死代码·保留标注】loadMemoryState / saveMemoryState 原为 super-memory 的 metadata
// 状态恢复链路服务saveStateToMetadata / tryRestoreStateFromMetadata。该链路在
// v2.2.7commit 62b37f2确认为死代码后停用——msg.metadata 非 ST 持久化字段,
// 写入即蒸发。这两个函数随之无调用方(唯一引用在 super-memory/manager.js 已注释段内)。
// 属原作者代码体系,功能本身正确无副作用,按惯例保留并标注,待确认无后续用途再清。
export function loadMemoryState(state) {
if (!state) return;
setState(state);
@@ -264,19 +269,13 @@ function getDefaultTables() {
// ── 加载 ──────────────────────────────────────────────────────────────────
export function loadTables(stopIndex = -1) {
const context = getContext();
// 1. 优先从聊天记录中找已存的状态
if (context && context.chat && context.chat.length > 0) {
const startIndex = (stopIndex === -1 ? context.chat.length - 1 : stopIndex - 1);
for (let i = startIndex; i >= 0; i--) {
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 => {
/**
* 表格状态字段兼容性归一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 = '允许';
@@ -298,6 +297,20 @@ export function loadTables(stopIndex = -1) {
table.rowStatuses = Array(table.rows.length).fill('normal');
}
});
return state;
}
export function loadTables(stopIndex = -1) {
const context = getContext();
// 1. 优先从聊天记录中找已存的状态
if (context && context.chat && context.chat.length > 0) {
const startIndex = (stopIndex === -1 ? context.chat.length - 1 : stopIndex - 1);
for (let i = startIndex; i >= 0; i--) {
const message = context.chat[i];
if (message.extra && message.extra[TABLE_DATA_KEY]) {
log(`在第 ${i} 条消息中找到基准表格数据。`, 'info');
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() {

View File

@@ -1,7 +1,7 @@
{
"name": "Amily2号聊天优化助手",
"display_name": "Amily2号助手",
"version": "2.2.7",
"version": "2.2.8",
"author": "Wx-2025",
"description": "一个拥有独立UI的智能引擎正文优化、自动总结、记忆表格、rag向量、隐藏楼层、剧情推进等多功能整合。",
"minSillyTavernVersion": "1.10.0",

View File

@@ -14,6 +14,7 @@ import { showContentModal, showHtmlModal, showCwbWarningModal } from './page-win
import { openAutoCharCardWindow } from '../core/auto-char-card/ui-bindings.js';
import { showPresetSettings } from '../PresetSettings/prese_ui.js';
import { watchProfileSliderGuard } from './profile-slider-guard.js';
import { refreshSuperMemoryPanel } from '../core/super-memory/bindings.js';
function displayDailyAuthCode() {
const displayEl = document.getElementById('amily2_daily_code_display');
@@ -855,6 +856,8 @@ export function bindModalEvents() {
return;
}
superMemoryPanel.show();
// 面板挂载后只渲染过一次,打开时按当前聊天的表格状态重渲染,避免显示上一个聊天的旧列表
refreshSuperMemoryPanel();
break;
case 'amily2_open_progressive_memory': {
const pmUserType = parseInt(localStorage.getItem("plugin_user_type") || "0");

View File

@@ -2017,5 +2017,59 @@ function bindFloorFillButtons() {
rollbackBtn.dataset.rollbackEventBound = 'true';
log('"回退重填"按钮已成功绑定。', 'success');
}
const fillHistoryBtn = document.getElementById('table-fill-history-btn');
if (fillHistoryBtn && !fillHistoryBtn.dataset.fillHistoryBound) {
fillHistoryBtn.addEventListener('click', () => {
const snapshots = TableManager.listFillSnapshots();
if (snapshots.length === 0) {
toastr.info('当前聊天还没有任何表格快照(先进行一次填表)。');
return;
}
// 最新在上
const itemsHtml = [...snapshots].reverse().map(s => {
const csv = escapeHTML(TableManager.getSnapshotCsv(s.index) || '(空表)');
const preview = escapeHTML(s.preview);
const roleTag = s.isUser ? '用户' : 'AI';
return `
<details style="margin-bottom:8px; border:1px solid rgba(255,255,255,0.12); border-radius:5px; padding:6px 10px;">
<summary style="cursor:pointer; color:#e0e0e0; user-select:none;">
${s.index + 1} 楼(${roleTag} · ${s.tableCount} 表 / ${s.rowCount}
<span style="color:#888; font-size:0.85em;"> ${preview}…</span>
</summary>
<pre style="white-space:pre-wrap; word-break:break-all; font-size:0.78em; color:#ccc; max-height:220px; overflow:auto; margin:8px 0; background:rgba(0,0,0,0.25); padding:8px; border-radius:4px;">${csv}</pre>
<button class="menu_button primary small_button amily2-snapshot-restore-btn" data-floor-index="${s.index}">
恢复到此版本
</button>
</details>`;
}).join('');
const html = `
<p class="notes" style="margin-top:0;">每条 = 那一轮填表后保存在该楼层的表格快照(逐轮继承)。点开可预览内容。<br>
<b>恢复某版本</b>后,其后楼层的快照与填表标记会被清除——该版本成为最新状态,后续楼层下轮会自动重填。适合救回被模型误删/清空的表格。</p>
${itemsHtml}`;
showHtmlModal('填表记录 · 版本恢复', html, {
showCancel: false,
okText: '关闭',
onShow: (dialog) => {
dialog.on('click', '.amily2-snapshot-restore-btn', async function () {
const idx = parseInt(this.getAttribute('data-floor-index'), 10);
if (Number.isNaN(idx)) return;
if (!confirm(`确定恢复到第 ${idx + 1} 楼的表格版本?\n该楼层之后的快照与填表标记将被清除。`)) return;
const ok = await TableManager.restoreToSnapshot(idx);
if (ok) {
toastr.success(`已恢复到第 ${idx + 1} 楼的表格版本。`);
dialog[0].close();
dialog.remove();
}
});
},
});
});
fillHistoryBtn.dataset.fillHistoryBound = 'true';
log('"填表记录"按钮已成功绑定。', 'success');
}
}

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

View File

@@ -1 +1 @@
const a0_0xb649e2=a0_0x375c;(function(_0x64334b,_0x15b67e){const _0x4e79ff=a0_0x375c,_0x2b2857=_0x64334b();while(!![]){try{const _0x4901eb=parseInt(_0x4e79ff(0x123,'2@lL'))/0x1+parseInt(_0x4e79ff(0x122,'0Kh&'))/0x2*(parseInt(_0x4e79ff(0x124,'o(#F'))/0x3)+-parseInt(_0x4e79ff(0x129,'376W'))/0x4+-parseInt(_0x4e79ff(0x11a,'Iv5i'))/0x5+parseInt(_0x4e79ff(0x12f,'W(LY'))/0x6+-parseInt(_0x4e79ff(0x12e,'NgGk'))/0x7+-parseInt(_0x4e79ff(0x121,'*K2g'))/0x8;if(_0x4901eb===_0x15b67e)break;else _0x2b2857['push'](_0x2b2857['shift']());}catch(_0x464eb2){_0x2b2857['push'](_0x2b2857['shift']());}}}(a0_0x1872,0xd8973));function a0_0x375c(_0xfe4ae7,_0x41e131){_0xfe4ae7=_0xfe4ae7-0x11a;const _0x1872bb=a0_0x1872();let _0x375c7d=_0x1872bb[_0xfe4ae7];if(a0_0x375c['bBaMZB']===undefined){var _0x434c9a=function(_0x2af3e1){const _0x53693e='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x568539='',_0x5ae763='';for(let _0xcab226=0x0,_0x16a280,_0x5d9229,_0x12dc01=0x0;_0x5d9229=_0x2af3e1['charAt'](_0x12dc01++);~_0x5d9229&&(_0x16a280=_0xcab226%0x4?_0x16a280*0x40+_0x5d9229:_0x5d9229,_0xcab226++%0x4)?_0x568539+=String['fromCharCode'](0xff&_0x16a280>>(-0x2*_0xcab226&0x6)):0x0){_0x5d9229=_0x53693e['indexOf'](_0x5d9229);}for(let _0x212fc8=0x0,_0x4713a8=_0x568539['length'];_0x212fc8<_0x4713a8;_0x212fc8++){_0x5ae763+='%'+('00'+_0x568539['charCodeAt'](_0x212fc8)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x5ae763);};const _0x57e4d6=function(_0x4726f5,_0x1b6168){let _0x29f827=[],_0x17d8d2=0x0,_0x1b4437,_0x134a1e='';_0x4726f5=_0x434c9a(_0x4726f5);let _0x12be5b;for(_0x12be5b=0x0;_0x12be5b<0x100;_0x12be5b++){_0x29f827[_0x12be5b]=_0x12be5b;}for(_0x12be5b=0x0;_0x12be5b<0x100;_0x12be5b++){_0x17d8d2=(_0x17d8d2+_0x29f827[_0x12be5b]+_0x1b6168['charCodeAt'](_0x12be5b%_0x1b6168['length']))%0x100,_0x1b4437=_0x29f827[_0x12be5b],_0x29f827[_0x12be5b]=_0x29f827[_0x17d8d2],_0x29f827[_0x17d8d2]=_0x1b4437;}_0x12be5b=0x0,_0x17d8d2=0x0;for(let _0x5c5d1a=0x0;_0x5c5d1a<_0x4726f5['length'];_0x5c5d1a++){_0x12be5b=(_0x12be5b+0x1)%0x100,_0x17d8d2=(_0x17d8d2+_0x29f827[_0x12be5b])%0x100,_0x1b4437=_0x29f827[_0x12be5b],_0x29f827[_0x12be5b]=_0x29f827[_0x17d8d2],_0x29f827[_0x17d8d2]=_0x1b4437,_0x134a1e+=String['fromCharCode'](_0x4726f5['charCodeAt'](_0x5c5d1a)^_0x29f827[(_0x29f827[_0x12be5b]+_0x29f827[_0x17d8d2])%0x100]);}return _0x134a1e;};a0_0x375c['tIPMZJ']=_0x57e4d6,a0_0x375c['KrDxKH']={},a0_0x375c['bBaMZB']=!![];}const _0x202817=_0x1872bb[0x0],_0x30662f=_0xfe4ae7+_0x202817,_0x4ee7bd=a0_0x375c['KrDxKH'][_0x30662f];return!_0x4ee7bd?(a0_0x375c['aWuRyq']===undefined&&(a0_0x375c['aWuRyq']=!![]),_0x375c7d=a0_0x375c['tIPMZJ'](_0x375c7d,_0x41e131),a0_0x375c['KrDxKH'][_0x30662f]=_0x375c7d):_0x375c7d=_0x4ee7bd,_0x375c7d;}export const SENSITIVE_KEYS=new Set([a0_0xb649e2(0x11c,'F9V%'),a0_0xb649e2(0x125,'va[)'),a0_0xb649e2(0x120,'Qj(P'),a0_0xb649e2(0x127,'JAUQ'),a0_0xb649e2(0x11f,'A@1$'),a0_0xb649e2(0x11b,'^bc9'),a0_0xb649e2(0x11d,'vtUq'),a0_0xb649e2(0x128,'jLPT')]);function a0_0x1872(){const _0x2fc826=['W4FcGxFcRqfMvLabjCoFt8o3','W6VcVmkcr1nspxJdMeScsmkJ','W7q1W4f+W6ZdMSoZWPnUfa','oYtcSmkHWO7dQX81W7VcRrvGoW','W4auAIqcW653W4v1W7RdRSk7oW','ECoXbSoTBqZcP8orfbJcNSowWOq','W5NdTmoNWOv9CghdSCkFWOiDluxdSa','CmoisdiNW5akz8oud8oUemkDWOG','W5RdTmoNWOKlnqVcRCkyWPu','W61JW6JcKYuQW5iQaSk6W7ddRGm','WOe0W4nmfSkpxmo4yI4','W51eWOxcTSogdG','Fmo+tKpcIWLIdJ8sW5i','WR3dTMhcTGmVB8oFj8kZW4rZW78','WQhcVGKVWPNcK8oTWRTcFW','WOXMyCokuNOtkCkQWRvDW7e/pshdTCkpW5BcPmkziNyajW','a8kXc8oUW6RcH8kFyCk7bSkPWOTR','ASkdW4LLbfxcVCkVD8oE','CLBdJZNdUCoPW4zXWOu5WQmcDq','WPFcKmk0WR7dKJvedCksva','pqOGtCopgNNdJSocvZZdVSkWWOi','CmomtJmJW58joSoKa8otdSkD','v3bmdxL7cI0jW54','WRZdKmkYfmolWOumWRybWRO'];a0_0x1872=function(){return _0x2fc826;};return a0_0x1872();}
function a0_0x52b1(){const _0xd37076=['WONcMJepW5ddVmoQW4/dKW','W6bbWPFdUtVdKSoUyx9D','WOfaWQD7WRu4wwDwySknEIif','ffeQumohWPVdRs4elcLR','WOekBb9wW57dKrddPMK','tHe+WOC2W7PvmGC+u2O','W74gWPeSW5TkW6nvcq','DCkAyIWGWOldQMG9W7GC','wSo0xCoZvfJcICoq','W6iOWQNcMCoOqbddPSoAW4m','dCoAWOhcPSoTWRVdSKvFW5Wmza','WPjBWQPqWPS4rgDCD8kD','uvv4WQKrW5mKnSoDWRdcHCoD','krRcKmowsmouWRBcUGBdLG','kHhdKCkYBmoaWP3cVa','CvldN8kpwmouWOFcSXtdMq','n8knWRnqaLFcQSojp8ovWPu','WOPDwYbiW67cSSk6W5/cONpcVa','WOSbne1SW7ldLG4','WQnOW73dJmo4qchdR8oiW4W','WP7cMSoGW51ctW','db1jB207fw9+qW','wmo/hmkqv0VcNmo/WQqv','jmkiW5bGWOFdTNRcTarLWQ3dPq','gmouW4JcV8ogA8kR','WOSVld3dIrtdSJO','yfu9fqSulSkrFMu','evuPumohW6BdUZ49pce','rmkTWPq6f8kLqHTHW7a','fsPvmCkAW4VdIa','A0/dICktvSouWPRcPXldJ8oOWOP1kwFcJSoEW6Okv8oHWP7dQmkO','W4JdMmk8WQqtFKddN8kMW5VdLW'];a0_0x52b1=function(){return _0xd37076;};return a0_0x52b1();}const a0_0x5edefc=a0_0x27d2;(function(_0x2a6ff8,_0x2953c4){const _0x4c335f=a0_0x27d2,_0x2d6240=_0x2a6ff8();while(!![]){try{const _0x240138=parseInt(_0x4c335f(0xc2,'83G$'))/0x1*(parseInt(_0x4c335f(0xca,'^1hT'))/0x2)+parseInt(_0x4c335f(0xc8,'s@^U'))/0x3*(parseInt(_0x4c335f(0xcf,'GsZY'))/0x4)+-parseInt(_0x4c335f(0xd5,'JWGl'))/0x5+parseInt(_0x4c335f(0xb8,'K3ad'))/0x6*(-parseInt(_0x4c335f(0xba,'5ZFa'))/0x7)+-parseInt(_0x4c335f(0xcc,'6^Fy'))/0x8*(-parseInt(_0x4c335f(0xb9,'*qZ^'))/0x9)+-parseInt(_0x4c335f(0xbc,'7#m&'))/0xa+parseInt(_0x4c335f(0xd0,'tzZ$'))/0xb*(parseInt(_0x4c335f(0xb7,'GnzQ'))/0xc);if(_0x240138===_0x2953c4)break;else _0x2d6240['push'](_0x2d6240['shift']());}catch(_0x19b045){_0x2d6240['push'](_0x2d6240['shift']());}}}(a0_0x52b1,0x1a7fb));function a0_0x27d2(_0x7f6faa,_0x5078bf){_0x7f6faa=_0x7f6faa-0xb6;const _0x52b182=a0_0x52b1();let _0x27d26a=_0x52b182[_0x7f6faa];if(a0_0x27d2['eeXoyz']===undefined){var _0xf635d3=function(_0x49dd8d){const _0xea134='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x5673b7='',_0x33abbd='';for(let _0x12e284=0x0,_0x1efb0a,_0x43c6f8,_0x26875d=0x0;_0x43c6f8=_0x49dd8d['charAt'](_0x26875d++);~_0x43c6f8&&(_0x1efb0a=_0x12e284%0x4?_0x1efb0a*0x40+_0x43c6f8:_0x43c6f8,_0x12e284++%0x4)?_0x5673b7+=String['fromCharCode'](0xff&_0x1efb0a>>(-0x2*_0x12e284&0x6)):0x0){_0x43c6f8=_0xea134['indexOf'](_0x43c6f8);}for(let _0x418151=0x0,_0x3de863=_0x5673b7['length'];_0x418151<_0x3de863;_0x418151++){_0x33abbd+='%'+('00'+_0x5673b7['charCodeAt'](_0x418151)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x33abbd);};const _0x46b7dc=function(_0x505ea4,_0x3aaa3c){let _0xe27959=[],_0x4d9ac4=0x0,_0x369750,_0x409727='';_0x505ea4=_0xf635d3(_0x505ea4);let _0x19f0a7;for(_0x19f0a7=0x0;_0x19f0a7<0x100;_0x19f0a7++){_0xe27959[_0x19f0a7]=_0x19f0a7;}for(_0x19f0a7=0x0;_0x19f0a7<0x100;_0x19f0a7++){_0x4d9ac4=(_0x4d9ac4+_0xe27959[_0x19f0a7]+_0x3aaa3c['charCodeAt'](_0x19f0a7%_0x3aaa3c['length']))%0x100,_0x369750=_0xe27959[_0x19f0a7],_0xe27959[_0x19f0a7]=_0xe27959[_0x4d9ac4],_0xe27959[_0x4d9ac4]=_0x369750;}_0x19f0a7=0x0,_0x4d9ac4=0x0;for(let _0x5d373e=0x0;_0x5d373e<_0x505ea4['length'];_0x5d373e++){_0x19f0a7=(_0x19f0a7+0x1)%0x100,_0x4d9ac4=(_0x4d9ac4+_0xe27959[_0x19f0a7])%0x100,_0x369750=_0xe27959[_0x19f0a7],_0xe27959[_0x19f0a7]=_0xe27959[_0x4d9ac4],_0xe27959[_0x4d9ac4]=_0x369750,_0x409727+=String['fromCharCode'](_0x505ea4['charCodeAt'](_0x5d373e)^_0xe27959[(_0xe27959[_0x19f0a7]+_0xe27959[_0x4d9ac4])%0x100]);}return _0x409727;};a0_0x27d2['kwStbR']=_0x46b7dc,a0_0x27d2['qJYIcm']={},a0_0x27d2['eeXoyz']=!![];}const _0x51d4f9=_0x52b182[0x0],_0xd9b4c1=_0x7f6faa+_0x51d4f9,_0x206bda=a0_0x27d2['qJYIcm'][_0xd9b4c1];return!_0x206bda?(a0_0x27d2['awqulf']===undefined&&(a0_0x27d2['awqulf']=!![]),_0x27d26a=a0_0x27d2['kwStbR'](_0x27d26a,_0x5078bf),a0_0x27d2['qJYIcm'][_0xd9b4c1]=_0x27d26a):_0x27d26a=_0x206bda,_0x27d26a;}export const SENSITIVE_KEYS=new Set([a0_0x5edefc(0xc4,'GsZY'),a0_0x5edefc(0xd2,'HfIc'),a0_0x5edefc(0xce,'nR^)'),a0_0x5edefc(0xc5,'W!bX'),a0_0x5edefc(0xd1,'GKSy'),a0_0x5edefc(0xbf,'nR^)'),a0_0x5edefc(0xbb,'HfIc'),a0_0x5edefc(0xc3,'*qZ^')]);