diff --git a/assets/renderer.css b/assets/renderer.css
new file mode 100644
index 0000000..1b47d7b
--- /dev/null
+++ b/assets/renderer.css
@@ -0,0 +1,26 @@
+#amily2_renderer_panel {
+ padding: 10px;
+}
+
+.amily2-renderer-info-container {
+ margin-top: 20px;
+ padding: 15px;
+ background-color: rgba(45, 45, 55, 0.5);
+ border-radius: 8px;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+}
+
+.emo-statement {
+ font-style: italic;
+ color: #d1c4e9;
+ text-align: center;
+ margin-bottom: 15px;
+ text-shadow: 0 0 5px rgba(209, 196, 233, 0.5);
+}
+
+.description-text {
+ font-size: 14px;
+ color: #dddddd;
+ line-height: 1.6;
+}
diff --git a/assets/style.css b/assets/style.css
index 738650a..0ce9acb 100644
--- a/assets/style.css
+++ b/assets/style.css
@@ -1,4 +1,3 @@
-
:root {
--amily2-bg-color: #2C2C2C;
--amily2-button-color: #4A4A4A;
@@ -172,6 +171,13 @@ hr.header-divider {
color: #ff9800;
}
+/* === Collapsible Legend Fix === */
+.collapsible-legend {
+ position: relative; /* Establish a stacking context */
+ z-index: 2; /* Ensure it's above sibling content */
+ cursor: pointer; /* Indicate it's clickable */
+}
+
#amily2_chat_optimiser .color-controls-container {
flex-direction: row !important;
@@ -719,3 +725,7 @@ hr.header-divider {
#amily2_chat_optimiser .prompt-editor-area textarea {
flex: 1;
}
+
+#amily2_test_api_connection {
+ margin-left: 10px;
+}
diff --git a/core/api.js b/core/api.js
index bec5333..139f560 100644
--- a/core/api.js
+++ b/core/api.js
@@ -379,30 +379,81 @@ async function fetchSillyTavernPresetModels() {
export function getApiSettings() {
+ const settings = extension_settings[extensionName] || {};
+ const apiProvider = document.getElementById('amily2_api_provider')?.value || 'openai';
+
+ let model;
+ if (apiProvider === 'sillytavern_preset') {
+ const context = getContext();
+ const profileId = document.getElementById('amily2_preset_selector')?.value;
+ const profile = context.extensionSettings?.connectionManager?.profiles?.find(p => p.id === profileId);
+ model = profile?.openai_model || 'Preset Model';
+ } else {
+ model = document.getElementById('amily2_model')?.value;
+ }
+
return {
- apiProvider: $("#amily2_api_provider").val() || 'openai',
- apiUrl: $("#amily2_api_url").val().trim(),
- apiKey: $("#amily2_api_key").val().trim(),
- model: $("#amily2_model").val(),
- maxTokens: extension_settings[extensionName]?.maxTokens || 4000,
- temperature: extension_settings[extensionName]?.temperature || 0.7,
- tavernProfile: extension_settings[extensionName]?.tavernProfile || ''
+ apiProvider: apiProvider,
+ apiUrl: document.getElementById('amily2_api_url')?.value.trim() || '',
+ apiKey: document.getElementById('amily2_api_key')?.value.trim() || '',
+ model: model,
+ maxTokens: settings.maxTokens || 4000,
+ temperature: settings.temperature || 0.7,
+ tavernProfile: document.getElementById('amily2_preset_selector')?.value || ''
};
}
export async function testApiConnection() {
console.log('[Amily2号-外交部] 开始API连接测试');
-
- const apiProvider = $("#amily2_api_provider").val() || 'openai';
- const models = await fetchModels();
-
- if (models.length > 0) {
- toastr.success(`${apiProvider} 提供商连接正常,找到 ${models.length} 个模型`, 'API连接正常');
- return true;
- } else {
- toastr.error('无法获取模型列表,请检查配置', 'API连接失败');
+ const $button = $("#amily2_test_api_connection");
+ if (!$button.length) return;
+
+ const originalHtml = $button.html();
+ $button.prop("disabled", true).html('
测试中');
+
+ try {
+ const apiSettings = getApiSettings();
+
+ if (apiSettings.apiProvider === 'sillytavern_preset') {
+ if (!apiSettings.tavernProfile) {
+ throw new Error("请先在下方选择一个SillyTavern预设");
+ }
+ } else {
+ if (!apiSettings.apiUrl || !apiSettings.apiKey || !apiSettings.model) {
+ throw new Error("API配置不完整,请检查URL、Key和模型选择");
+ }
+ }
+
+ toastr.info('正在发送测试消息"你好!"...', 'API连接测试');
+
+ const userName = getContext()?.name1 || '用户';
+ const systemPrompt = `接下来用户会使用测试按钮测试api连接是否正常,请回复ta连接是正常的,称呼用户为:“${userName}大人”,并复述群号1060183271,告知ta,本扩展开发者:“诗与酒.”正静待ta的入驻。`;
+
+ const testMessages = [
+ { role: 'system', content: systemPrompt },
+ { role: 'user', content: '你好!' }
+ ];
+
+ const response = await callAI(testMessages, {
+ maxTokens: 8192,
+ temperature: 0.5
+ });
+
+ if (response && response.trim()) {
+ console.log('[Amily2号-外交部] 测试消息响应:', response);
+ toastr.success(`连接测试成功!AI回复: "${response}"`, 'API连接测试成功');
+ return true;
+ } else {
+ throw new Error('API未返回有效响应,请检查您的代理、API URL和密钥是否正确。这通常发生在网络问题或认证失败时。');
+ }
+
+ } catch (error) {
+ console.error('[Amily2号-使节团] API连接测试失败:', error);
+ toastr.error(`连接测试失败: ${error.message}`, 'API连接测试失败');
return false;
+ } finally {
+ $button.prop("disabled", false).html(originalHtml);
}
}
@@ -531,28 +582,30 @@ async function callOpenAICompatible(messages, options) {
}
async function callOpenAITest(messages, options) {
+ const body = {
+ chat_completion_source: 'openai',
+ messages: messages,
+ model: options.model,
+ reverse_proxy: options.apiUrl,
+ proxy_password: options.apiKey,
+ stream: false,
+ max_tokens: options.maxTokens || 30000,
+ temperature: options.temperature || 1,
+ top_p: options.top_p || 1,
+ custom_prompt_post_processing: 'strict',
+ enable_web_search: false,
+ frequency_penalty: 0,
+ group_names: [],
+ include_reasoning: false,
+ presence_penalty: 0.12,
+ reasoning_effort: 'medium',
+ request_images: false,
+ };
+
const response = await fetch('/api/backends/chat-completions/generate', {
method: 'POST',
headers: { ...getRequestHeaders(), 'Content-Type': 'application/json' },
- body: JSON.stringify({
- chat_completion_source: 'openai',
- custom_prompt_post_processing: 'strict',
- enable_web_search: false,
- frequency_penalty: 0,
- group_names: [],
- include_reasoning: false,
- max_tokens: options.maxTokens || 100000,
- messages: messages,
- model: options.model,
- presence_penalty: 0.12,
- proxy_password: options.apiKey,
- reasoning_effort: 'medium',
- request_images: false,
- reverse_proxy: options.apiUrl,
- stream: false,
- temperature: options.temperature || 1,
- top_p: options.top_p || 1
- })
+ body: JSON.stringify(body)
});
if (!response.ok) {
@@ -561,6 +614,15 @@ async function callOpenAITest(messages, options) {
}
const responseData = await response.json();
+
+ if (!responseData || !responseData.choices || responseData.choices.length === 0) {
+ console.error('[Amily2号-OpenAI兼容(测试)] API返回了空的choices数组或错误:', responseData);
+ if (responseData.error) {
+ throw new Error(`API返回错误: ${responseData.error.message || JSON.stringify(responseData.error)}`);
+ }
+ return null;
+ }
+
return responseData?.choices?.[0]?.message?.content;
}
diff --git a/core/api/JqyhApi.js b/core/api/JqyhApi.js
index a889d50..9a4fb34 100644
--- a/core/api/JqyhApi.js
+++ b/core/api/JqyhApi.js
@@ -1,386 +1,383 @@
-import { extension_settings, getContext } from "/scripts/extensions.js";
-import { characters, this_chid, getRequestHeaders, saveSettingsDebounced, eventSource, event_types } from "/script.js";
-import { extensionName } from "../../utils/settings.js";
-
-let ChatCompletionService = undefined;
-try {
- const module = await import('/scripts/custom-request.js');
- ChatCompletionService = module.ChatCompletionService;
- console.log('[Amily2号-Jqyh外交部] 已成功召唤"皇家信使"(ChatCompletionService)。');
-} catch (e) {
- console.warn("[Amily2号-Jqyh外交部] 未能召唤“皇家信使”,部分高级功能(如Claw代理)将受限。请考虑更新SillyTavern版本。", e);
-}
-
-function normalizeApiResponse(responseData) {
- let data = responseData;
- if (typeof data === 'string') {
- try {
- data = JSON.parse(data);
- } catch (e) {
- console.error(`[${extensionName}] Jqyh API响应JSON解析失败:`, e);
- return { error: { message: 'Invalid JSON response' } };
- }
- }
- if (data && typeof data.data === 'object' && data.data !== null && !Array.isArray(data.data)) {
- if (Object.hasOwn(data.data, 'data')) {
- data = data.data;
- }
- }
- if (data && data.choices && data.choices[0]) {
- return { content: data.choices[0].message?.content?.trim() };
- }
- if (data && data.content) {
- return { content: data.content.trim() };
- }
- if (data && data.data) {
- return { data: data.data };
- }
- if (data && data.error) {
- return { error: data.error };
- }
- return data;
-}
-
-export function getJqyhApiSettings() {
- return {
- apiMode: extension_settings[extensionName]?.jqyhApiMode || 'openai_test',
- apiUrl: extension_settings[extensionName]?.jqyhApiUrl?.trim() || '',
- apiKey: extension_settings[extensionName]?.jqyhApiKey?.trim() || '',
- model: extension_settings[extensionName]?.jqyhModel || '',
- maxTokens: extension_settings[extensionName]?.jqyhMaxTokens || 4000,
- temperature: extension_settings[extensionName]?.jqyhTemperature || 0.7,
- tavernProfile: extension_settings[extensionName]?.jqyhTavernProfile || ''
- };
-}
-
-export async function callJqyhAI(messages, options = {}) {
- if (window.AMILY2_SYSTEM_PARALYZED === true) {
- console.error("[Amily2-Jqyh制裁] 系统完整性已受损,所有外交活动被无限期中止。");
- return null;
- }
-
- const apiSettings = getJqyhApiSettings();
-
- const finalOptions = {
- maxTokens: apiSettings.maxTokens,
- temperature: apiSettings.temperature,
- model: apiSettings.model,
- apiUrl: apiSettings.apiUrl,
- apiKey: apiSettings.apiKey,
- apiMode: apiSettings.apiMode,
- tavernProfile: apiSettings.tavernProfile,
- ...options
- };
-
- if (finalOptions.apiMode !== 'sillytavern_preset') {
- if (!finalOptions.apiUrl || !finalOptions.model || !finalOptions.apiKey) {
- console.warn("[Amily2-Jqyh外交部] API配置不完整,无法调用AI");
- toastr.error("API配置不完整,请检查URL、Key和模型配置。", "Jqyh-外交部");
- return null;
- }
- }
-
- console.groupCollapsed(`[Amily2号-Jqyh统一API调用] ${new Date().toLocaleTimeString()}`);
- console.log("【请求参数】:", {
- mode: finalOptions.apiMode,
- model: finalOptions.model,
- maxTokens: finalOptions.maxTokens,
- temperature: finalOptions.temperature,
- messagesCount: messages.length
- });
- console.log("【消息内容】:", messages);
- console.groupEnd();
-
- try {
- let responseContent;
-
- switch (finalOptions.apiMode) {
- case 'openai_test':
- responseContent = await callJqyhOpenAITest(messages, finalOptions);
- break;
- case 'sillytavern_preset':
- responseContent = await callJqyhSillyTavernPreset(messages, finalOptions);
- break;
- default:
- console.error(`[Amily2-Jqyh外交部] 未支持的API模式: ${finalOptions.apiMode}`);
- return null;
- }
-
- if (!responseContent) {
- console.warn('[Amily2-Jqyh外交部] 未能获取AI响应内容');
- return null;
- }
-
- console.groupCollapsed("[Amily2号-Jqyh AI回复]");
- console.log(responseContent);
- console.groupEnd();
-
- return responseContent;
-
- } catch (error) {
- console.error(`[Amily2-Jqyh外交部] API调用发生错误:`, error);
-
- if (error.message.includes('400')) {
- toastr.error(`API请求格式错误 (400): 请检查消息格式和模型配置`, "Jqyh API调用失败");
- } else if (error.message.includes('401')) {
- toastr.error(`API认证失败 (401): 请检查API Key配置`, "Jqyh API调用失败");
- } else if (error.message.includes('403')) {
- toastr.error(`API访问被拒绝 (403): 请检查权限设置`, "Jqyh API调用失败");
- } else if (error.message.includes('429')) {
- toastr.error(`API调用频率超限 (429): 请稍后重试`, "Jqyh API调用失败");
- } else if (error.message.includes('500')) {
- toastr.error(`API服务器错误 (500): 请稍后重试`, "Jqyh API调用失败");
- } else {
- toastr.error(`API调用失败: ${error.message}`, "Jqyh API调用失败");
- }
-
- return null;
- }
-}
-
-async function callJqyhOpenAITest(messages, options) {
- const isGoogleApi = options.apiUrl.includes('googleapis.com');
-
- const body = {
- chat_completion_source: 'openai',
- messages: messages,
- model: options.model,
- reverse_proxy: options.apiUrl,
- proxy_password: options.apiKey,
- stream: false,
- max_tokens: options.maxTokens || 30000,
- temperature: options.temperature || 1,
- top_p: options.top_p || 1,
- };
-
- if (!isGoogleApi) {
- Object.assign(body, {
- custom_prompt_post_processing: 'strict',
- enable_web_search: false,
- frequency_penalty: 0,
- group_names: [],
- include_reasoning: false,
- presence_penalty: 0.12,
- reasoning_effort: 'medium',
- request_images: false,
- });
- }
-
- const response = await fetch('/api/backends/chat-completions/generate', {
- method: 'POST',
- headers: { ...getRequestHeaders(), 'Content-Type': 'application/json' },
- body: JSON.stringify(body)
- });
-
- if (!response.ok) {
- const errorText = await response.text();
- throw new Error(`Jqyh全兼容API请求失败: ${response.status} - ${errorText}`);
- }
-
- const responseData = await response.json();
- return responseData?.choices?.[0]?.message?.content;
-}
-
-async function callJqyhSillyTavernPreset(messages, options) {
- console.log('[Amily2号-JqyhST预设] 使用SillyTavern预设调用');
-
- if (!window.TavernHelper || !window.TavernHelper.triggerSlash) {
- throw new Error('TavernHelper不可用,无法使用SillyTavern预设模式');
- }
-
- const context = getContext();
- if (!context) {
- throw new Error('无法获取SillyTavern上下文');
- }
-
- const profileId = options.tavernProfile;
- if (!profileId) {
- throw new Error('未配置SillyTavern预设ID');
- }
-
- let originalProfile = '';
- let responsePromise;
-
- try {
- originalProfile = await window.TavernHelper.triggerSlash('/profile');
- console.log(`[Amily2号-JqyhST预设] 当前配置文件: ${originalProfile}`);
-
- const targetProfile = context.extensionSettings?.connectionManager?.profiles?.find(p => p.id === profileId);
- if (!targetProfile) {
- throw new Error(`未找到配置文件ID: ${profileId}`);
- }
-
- const targetProfileName = targetProfile.name;
- console.log(`[Amily2号-JqyhST预设] 目标配置文件: ${targetProfileName}`);
-
- const currentProfile = await window.TavernHelper.triggerSlash('/profile');
- if (currentProfile !== targetProfileName) {
- console.log(`[Amily2号-JqyhST预设] 切换配置文件: ${currentProfile} -> ${targetProfileName}`);
- const escapedProfileName = targetProfileName.replace(/"/g, '\\"');
- await window.TavernHelper.triggerSlash(`/profile await=true "${escapedProfileName}"`);
- }
-
- if (!context.ConnectionManagerRequestService) {
- throw new Error('ConnectionManagerRequestService不可用');
- }
-
- console.log(`[Amily2号-JqyhST预设] 通过配置文件 ${targetProfileName} 发送请求`);
- responsePromise = context.ConnectionManagerRequestService.sendRequest(
- targetProfile.id,
- messages,
- options.maxTokens || 4000
- );
-
- } finally {
- try {
- const currentProfileAfterCall = await window.TavernHelper.triggerSlash('/profile');
- if (originalProfile && originalProfile !== currentProfileAfterCall) {
- console.log(`[Amily2号-JqyhST预设] 恢复原始配置文件: ${currentProfileAfterCall} -> ${originalProfile}`);
- const escapedOriginalProfile = originalProfile.replace(/"/g, '\\"');
- await window.TavernHelper.triggerSlash(`/profile await=true "${escapedOriginalProfile}"`);
- }
- } catch (restoreError) {
- console.error('[Amily2号-JqyhST预设] 恢复配置文件失败:', restoreError);
- }
- }
-
- const result = await responsePromise;
-
- if (!result) {
- throw new Error('未收到API响应');
- }
-
- const normalizedResult = normalizeApiResponse(result);
- if (normalizedResult.error) {
- throw new Error(normalizedResult.error.message || 'SillyTavern预设API调用失败');
- }
-
- return normalizedResult.content;
-}
-
-export async function fetchJqyhModels() {
- console.log('[Amily2号-Jqyh外交部] 开始获取模型列表');
-
- const apiSettings = getJqyhApiSettings();
-
- try {
- if (apiSettings.apiMode === 'sillytavern_preset') {
- const context = getContext();
- if (!context?.extensionSettings?.connectionManager?.profiles) {
- throw new Error('无法获取SillyTavern配置文件列表');
- }
-
- const targetProfile = context.extensionSettings.connectionManager.profiles.find(p => p.id === apiSettings.tavernProfile);
- if (!targetProfile) {
- throw new Error(`未找到配置文件ID: ${apiSettings.tavernProfile}`);
- }
-
- const models = [];
- if (targetProfile.openai_model) {
- models.push({ id: targetProfile.openai_model, name: targetProfile.openai_model });
- }
-
- if (models.length === 0) {
- throw new Error('当前预设未配置模型');
- }
-
- console.log('[Amily2号-Jqyh外交部] SillyTavern预设模式获取到模型:', models);
- return models;
-
- } else {
- if (!apiSettings.apiUrl || !apiSettings.apiKey) {
- throw new Error('API URL或Key未配置');
- }
-
- const response = await fetch('/api/backends/chat-completions/status', {
- method: 'POST',
- headers: {
- ...getRequestHeaders(),
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- reverse_proxy: apiSettings.apiUrl,
- proxy_password: apiSettings.apiKey,
- chat_completion_source: 'openai'
- })
- });
-
- if (!response.ok) {
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
- }
-
- const rawData = await response.json();
- const models = Array.isArray(rawData) ? rawData : (rawData.data || rawData.models || []);
-
- if (!Array.isArray(models)) {
- const errorMessage = result.error?.message || 'API未返回有效的模型列表数组';
- throw new Error(errorMessage);
- }
-
- const formattedModels = models
- .map(m => {
- const modelIdRaw = m.name || m.id || m.model || m;
- const modelName = String(modelIdRaw).replace(/^models\//, '');
- return {
- id: modelName,
- name: modelName
- };
- })
- .filter(m => m.id)
- .sort((a, b) => String(a.name).localeCompare(String(b.name)));
-
- console.log('[Amily2号-Jqyh外交部] 全兼容模式获取到模型:', formattedModels);
- return formattedModels;
- }
- } catch (error) {
- console.error('[Amily2号-Jqyh外交部] 获取模型列表失败:', error);
- toastr.error(`获取模型列表失败: ${error.message}`, 'Jqyh API');
- throw error;
- }
-}
-
-export async function testJqyhApiConnection() {
- console.log('[Amily2号-Jqyh外交部] 开始API连接测试');
-
- const apiSettings = getJqyhApiSettings();
-
- if (apiSettings.apiMode === 'sillytavern_preset') {
- if (!apiSettings.tavernProfile) {
- toastr.error('未配置SillyTavern预设ID', 'Jqyh API连接测试失败');
- return false;
- }
- } else {
- if (!apiSettings.apiUrl || !apiSettings.apiKey || !apiSettings.model) {
- toastr.error('API配置不完整,请检查URL、Key和模型', 'Jqyh API连接测试失败');
- return false;
- }
- }
-
- try {
- toastr.info('正在发送测试消息"你好!"...', 'Jqyh API连接测试');
-
- const userName = window.SillyTavern.getContext?.()?.name1 || '用户';
- const systemPrompt = `接下来用户会使用测试按钮测试api连接是否正常,请回复ta连接是正常的,称呼用户为:“${userName}大人”,并复述群号1060183271,告知ta,本扩展开发者:“诗与酒.”正静待ta的入驻。`;
-
- const testMessages = [
- { role: 'system', content: systemPrompt },
- { role: 'user', content: '你好!' }
- ];
-
- const response = await callJqyhAI(testMessages);
-
- if (response && response.trim()) {
- console.log('[Amily2号-Jqyh外交部] 测试消息响应:', response);
- const formattedResponse = response.replace(/\*\*(.*?)\*\*/g, '
$1');
- toastr.success(`连接测试成功!AI回复: "${formattedResponse}"`, 'Jqyh API连接测试成功', { "escapeHtml": false });
- return true;
- } else {
- throw new Error('API未返回有效响应');
- }
-
- } catch (error) {
- console.error('[Amily2号-Jqyh外交部] 连接测试失败:', error);
- toastr.error(`连接测试失败: ${error.message}`, 'Jqyh API连接测试失败');
- return false;
- }
-}
+import { extension_settings, getContext } from "/scripts/extensions.js";
+import { characters, this_chid, getRequestHeaders, saveSettingsDebounced, eventSource, event_types } from "/script.js";
+import { extensionName } from "../../utils/settings.js";
+import { amilyHelper } from '../../core/tavern-helper/main.js';
+
+let ChatCompletionService = undefined;
+try {
+ const module = await import('/scripts/custom-request.js');
+ ChatCompletionService = module.ChatCompletionService;
+ console.log('[Amily2号-Jqyh外交部] 已成功召唤"皇家信使"(ChatCompletionService)。');
+} catch (e) {
+ console.warn("[Amily2号-Jqyh外交部] 未能召唤“皇家信使”,部分高级功能(如Claw代理)将受限。请考虑更新SillyTavern版本。", e);
+}
+
+function normalizeApiResponse(responseData) {
+ let data = responseData;
+ if (typeof data === 'string') {
+ try {
+ data = JSON.parse(data);
+ } catch (e) {
+ console.error(`[${extensionName}] Jqyh API响应JSON解析失败:`, e);
+ return { error: { message: 'Invalid JSON response' } };
+ }
+ }
+ if (data && typeof data.data === 'object' && data.data !== null && !Array.isArray(data.data)) {
+ if (Object.hasOwn(data.data, 'data')) {
+ data = data.data;
+ }
+ }
+ if (data && data.choices && data.choices[0]) {
+ return { content: data.choices[0].message?.content?.trim() };
+ }
+ if (data && data.content) {
+ return { content: data.content.trim() };
+ }
+ if (data && data.data) {
+ return { data: data.data };
+ }
+ if (data && data.error) {
+ return { error: data.error };
+ }
+ return data;
+}
+
+export function getJqyhApiSettings() {
+ return {
+ apiMode: extension_settings[extensionName]?.jqyhApiMode || 'openai_test',
+ apiUrl: extension_settings[extensionName]?.jqyhApiUrl?.trim() || '',
+ apiKey: extension_settings[extensionName]?.jqyhApiKey?.trim() || '',
+ model: extension_settings[extensionName]?.jqyhModel || '',
+ maxTokens: extension_settings[extensionName]?.jqyhMaxTokens || 4000,
+ temperature: extension_settings[extensionName]?.jqyhTemperature || 0.7,
+ tavernProfile: extension_settings[extensionName]?.jqyhTavernProfile || ''
+ };
+}
+
+export async function callJqyhAI(messages, options = {}) {
+ if (window.AMILY2_SYSTEM_PARALYZED === true) {
+ console.error("[Amily2-Jqyh制裁] 系统完整性已受损,所有外交活动被无限期中止。");
+ return null;
+ }
+
+ const apiSettings = getJqyhApiSettings();
+
+ const finalOptions = {
+ maxTokens: apiSettings.maxTokens,
+ temperature: apiSettings.temperature,
+ model: apiSettings.model,
+ apiUrl: apiSettings.apiUrl,
+ apiKey: apiSettings.apiKey,
+ apiMode: apiSettings.apiMode,
+ tavernProfile: apiSettings.tavernProfile,
+ ...options
+ };
+
+ if (finalOptions.apiMode !== 'sillytavern_preset') {
+ if (!finalOptions.apiUrl || !finalOptions.model || !finalOptions.apiKey) {
+ console.warn("[Amily2-Jqyh外交部] API配置不完整,无法调用AI");
+ toastr.error("API配置不完整,请检查URL、Key和模型配置。", "Jqyh-外交部");
+ return null;
+ }
+ }
+
+ console.groupCollapsed(`[Amily2号-Jqyh统一API调用] ${new Date().toLocaleTimeString()}`);
+ console.log("【请求参数】:", {
+ mode: finalOptions.apiMode,
+ model: finalOptions.model,
+ maxTokens: finalOptions.maxTokens,
+ temperature: finalOptions.temperature,
+ messagesCount: messages.length
+ });
+ console.log("【消息内容】:", messages);
+ console.groupEnd();
+
+ try {
+ let responseContent;
+
+ switch (finalOptions.apiMode) {
+ case 'openai_test':
+ responseContent = await callJqyhOpenAITest(messages, finalOptions);
+ break;
+ case 'sillytavern_preset':
+ responseContent = await callJqyhSillyTavernPreset(messages, finalOptions);
+ break;
+ default:
+ console.error(`[Amily2-Jqyh外交部] 未支持的API模式: ${finalOptions.apiMode}`);
+ return null;
+ }
+
+ if (!responseContent) {
+ console.warn('[Amily2-Jqyh外交部] 未能获取AI响应内容');
+ return null;
+ }
+
+ console.groupCollapsed("[Amily2号-Jqyh AI回复]");
+ console.log(responseContent);
+ console.groupEnd();
+
+ return responseContent;
+
+ } catch (error) {
+ console.error(`[Amily2-Jqyh外交部] API调用发生错误:`, error);
+
+ if (error.message.includes('400')) {
+ toastr.error(`API请求格式错误 (400): 请检查消息格式和模型配置`, "Jqyh API调用失败");
+ } else if (error.message.includes('401')) {
+ toastr.error(`API认证失败 (401): 请检查API Key配置`, "Jqyh API调用失败");
+ } else if (error.message.includes('403')) {
+ toastr.error(`API访问被拒绝 (403): 请检查权限设置`, "Jqyh API调用失败");
+ } else if (error.message.includes('429')) {
+ toastr.error(`API调用频率超限 (429): 请稍后重试`, "Jqyh API调用失败");
+ } else if (error.message.includes('500')) {
+ toastr.error(`API服务器错误 (500): 请稍后重试`, "Jqyh API调用失败");
+ } else {
+ toastr.error(`API调用失败: ${error.message}`, "Jqyh API调用失败");
+ }
+
+ return null;
+ }
+}
+
+async function callJqyhOpenAITest(messages, options) {
+ const isGoogleApi = options.apiUrl.includes('googleapis.com');
+
+ const body = {
+ chat_completion_source: 'openai',
+ messages: messages,
+ model: options.model,
+ reverse_proxy: options.apiUrl,
+ proxy_password: options.apiKey,
+ stream: false,
+ max_tokens: options.maxTokens || 30000,
+ temperature: options.temperature || 1,
+ top_p: options.top_p || 1,
+ };
+
+ if (!isGoogleApi) {
+ Object.assign(body, {
+ custom_prompt_post_processing: 'strict',
+ enable_web_search: false,
+ frequency_penalty: 0,
+ group_names: [],
+ include_reasoning: false,
+ presence_penalty: 0.12,
+ reasoning_effort: 'medium',
+ request_images: false,
+ });
+ }
+
+ const response = await fetch('/api/backends/chat-completions/generate', {
+ method: 'POST',
+ headers: { ...getRequestHeaders(), 'Content-Type': 'application/json' },
+ body: JSON.stringify(body)
+ });
+
+ if (!response.ok) {
+ const errorText = await response.text();
+ throw new Error(`Jqyh全兼容API请求失败: ${response.status} - ${errorText}`);
+ }
+
+ const responseData = await response.json();
+ return responseData?.choices?.[0]?.message?.content;
+}
+
+async function callJqyhSillyTavernPreset(messages, options) {
+ console.log('[Amily2号-JqyhST预设] 使用SillyTavern预设调用');
+
+ const context = getContext();
+ if (!context) {
+ throw new Error('无法获取SillyTavern上下文');
+ }
+
+ const profileId = options.tavernProfile;
+ if (!profileId) {
+ throw new Error('未配置SillyTavern预设ID');
+ }
+
+ let originalProfile = '';
+ let responsePromise;
+
+ try {
+ originalProfile = await amilyHelper.triggerSlash('/profile');
+ console.log(`[Amily2号-JqyhST预设] 当前配置文件: ${originalProfile}`);
+
+ const targetProfile = context.extensionSettings?.connectionManager?.profiles?.find(p => p.id === profileId);
+ if (!targetProfile) {
+ throw new Error(`未找到配置文件ID: ${profileId}`);
+ }
+
+ const targetProfileName = targetProfile.name;
+ console.log(`[Amily2号-JqyhST预设] 目标配置文件: ${targetProfileName}`);
+
+ const currentProfile = await amilyHelper.triggerSlash('/profile');
+ if (currentProfile !== targetProfileName) {
+ console.log(`[Amily2号-JqyhST预设] 切换配置文件: ${currentProfile} -> ${targetProfileName}`);
+ const escapedProfileName = targetProfileName.replace(/"/g, '\\"');
+ await amilyHelper.triggerSlash(`/profile await=true "${escapedProfileName}"`);
+ }
+
+ if (!context.ConnectionManagerRequestService) {
+ throw new Error('ConnectionManagerRequestService不可用');
+ }
+
+ console.log(`[Amily2号-JqyhST预设] 通过配置文件 ${targetProfileName} 发送请求`);
+ responsePromise = context.ConnectionManagerRequestService.sendRequest(
+ targetProfile.id,
+ messages,
+ options.maxTokens || 4000
+ );
+
+ } finally {
+ try {
+ const currentProfileAfterCall = await amilyHelper.triggerSlash('/profile');
+ if (originalProfile && originalProfile !== currentProfileAfterCall) {
+ console.log(`[Amily2号-JqyhST预设] 恢复原始配置文件: ${currentProfileAfterCall} -> ${originalProfile}`);
+ const escapedOriginalProfile = originalProfile.replace(/"/g, '\\"');
+ await amilyHelper.triggerSlash(`/profile await=true "${escapedOriginalProfile}"`);
+ }
+ } catch (restoreError) {
+ console.error('[Amily2号-JqyhST预设] 恢复配置文件失败:', restoreError);
+ }
+ }
+
+ const result = await responsePromise;
+
+ if (!result) {
+ throw new Error('未收到API响应');
+ }
+
+ const normalizedResult = normalizeApiResponse(result);
+ if (normalizedResult.error) {
+ throw new Error(normalizedResult.error.message || 'SillyTavern预设API调用失败');
+ }
+
+ return normalizedResult.content;
+}
+
+export async function fetchJqyhModels() {
+ console.log('[Amily2号-Jqyh外交部] 开始获取模型列表');
+
+ const apiSettings = getJqyhApiSettings();
+
+ try {
+ if (apiSettings.apiMode === 'sillytavern_preset') {
+ const context = getContext();
+ if (!context?.extensionSettings?.connectionManager?.profiles) {
+ throw new Error('无法获取SillyTavern配置文件列表');
+ }
+
+ const targetProfile = context.extensionSettings.connectionManager.profiles.find(p => p.id === apiSettings.tavernProfile);
+ if (!targetProfile) {
+ throw new Error(`未找到配置文件ID: ${apiSettings.tavernProfile}`);
+ }
+
+ const models = [];
+ if (targetProfile.openai_model) {
+ models.push({ id: targetProfile.openai_model, name: targetProfile.openai_model });
+ }
+
+ if (models.length === 0) {
+ throw new Error('当前预设未配置模型');
+ }
+
+ console.log('[Amily2号-Jqyh外交部] SillyTavern预设模式获取到模型:', models);
+ return models;
+
+ } else {
+ if (!apiSettings.apiUrl || !apiSettings.apiKey) {
+ throw new Error('API URL或Key未配置');
+ }
+
+ const response = await fetch('/api/backends/chat-completions/status', {
+ method: 'POST',
+ headers: {
+ ...getRequestHeaders(),
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ reverse_proxy: apiSettings.apiUrl,
+ proxy_password: apiSettings.apiKey,
+ chat_completion_source: 'openai'
+ })
+ });
+
+ if (!response.ok) {
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
+ }
+
+ const rawData = await response.json();
+ const models = Array.isArray(rawData) ? rawData : (rawData.data || rawData.models || []);
+
+ if (!Array.isArray(models)) {
+ const errorMessage = result.error?.message || 'API未返回有效的模型列表数组';
+ throw new Error(errorMessage);
+ }
+
+ const formattedModels = models
+ .map(m => {
+ const modelIdRaw = m.name || m.id || m.model || m;
+ const modelName = String(modelIdRaw).replace(/^models\//, '');
+ return {
+ id: modelName,
+ name: modelName
+ };
+ })
+ .filter(m => m.id)
+ .sort((a, b) => String(a.name).localeCompare(String(b.name)));
+
+ console.log('[Amily2号-Jqyh外交部] 全兼容模式获取到模型:', formattedModels);
+ return formattedModels;
+ }
+ } catch (error) {
+ console.error('[Amily2号-Jqyh外交部] 获取模型列表失败:', error);
+ toastr.error(`获取模型列表失败: ${error.message}`, 'Jqyh API');
+ throw error;
+ }
+}
+
+export async function testJqyhApiConnection() {
+ console.log('[Amily2号-Jqyh外交部] 开始API连接测试');
+
+ const apiSettings = getJqyhApiSettings();
+
+ if (apiSettings.apiMode === 'sillytavern_preset') {
+ if (!apiSettings.tavernProfile) {
+ toastr.error('未配置SillyTavern预设ID', 'Jqyh API连接测试失败');
+ return false;
+ }
+ } else {
+ if (!apiSettings.apiUrl || !apiSettings.apiKey || !apiSettings.model) {
+ toastr.error('API配置不完整,请检查URL、Key和模型', 'Jqyh API连接测试失败');
+ return false;
+ }
+ }
+
+ try {
+ toastr.info('正在发送测试消息"你好!"...', 'Jqyh API连接测试');
+
+ const userName = window.SillyTavern.getContext?.()?.name1 || '用户';
+ const systemPrompt = `接下来用户会使用测试按钮测试api连接是否正常,请回复ta连接是正常的,称呼用户为:“${userName}大人”,并复述群号1060183271,告知ta,本扩展开发者:“诗与酒.”正静待ta的入驻。`;
+
+ const testMessages = [
+ { role: 'system', content: systemPrompt },
+ { role: 'user', content: '你好!' }
+ ];
+
+ const response = await callJqyhAI(testMessages);
+
+ if (response && response.trim()) {
+ console.log('[Amily2号-Jqyh外交部] 测试消息响应:', response);
+ const formattedResponse = response.replace(/\*\*(.*?)\*\*/g, '
$1');
+ toastr.success(`连接测试成功!AI回复: "${formattedResponse}"`, 'Jqyh API连接测试成功', { "escapeHtml": false });
+ return true;
+ } else {
+ throw new Error('API未返回有效响应');
+ }
+
+ } catch (error) {
+ console.error('[Amily2号-Jqyh外交部] 连接测试失败:', error);
+ toastr.error(`连接测试失败: ${error.message}`, 'Jqyh API连接测试失败');
+ return false;
+ }
+}
diff --git a/core/api/NccsApi.js b/core/api/NccsApi.js
index bb05df6..fc42cab 100644
--- a/core/api/NccsApi.js
+++ b/core/api/NccsApi.js
@@ -1,388 +1,385 @@
-import { extension_settings, getContext } from "/scripts/extensions.js";
-import { characters, this_chid, getRequestHeaders, saveSettingsDebounced, eventSource, event_types } from "/script.js";
-import { extensionName } from "../../utils/settings.js";
-
-let ChatCompletionService = undefined;
-try {
- const module = await import('/scripts/custom-request.js');
- ChatCompletionService = module.ChatCompletionService;
- console.log('[Amily2号-Nccs外交部] 已成功召唤"皇家信使"(ChatCompletionService)。');
-} catch (e) {
- console.warn("[Amily2号-Nccs外交部] 未能召唤“皇家信使”,部分高级功能(如Claw代理)将受限。请考虑更新SillyTavern版本。", e);
-}
-
-function normalizeApiResponse(responseData) {
- let data = responseData;
- if (typeof data === 'string') {
- try {
- data = JSON.parse(data);
- } catch (e) {
- console.error(`[${extensionName}] Nccs API响应JSON解析失败:`, e);
- return { error: { message: 'Invalid JSON response' } };
- }
- }
- if (data && typeof data.data === 'object' && data.data !== null && !Array.isArray(data.data)) {
- if (Object.hasOwn(data.data, 'data')) {
- data = data.data;
- }
- }
- if (data && data.choices && data.choices[0]) {
- return { content: data.choices[0].message?.content?.trim() };
- }
- if (data && data.content) {
- return { content: data.content.trim() };
- }
- if (data && data.data) {
- return { data: data.data };
- }
- if (data && data.error) {
- return { error: data.error };
- }
- return data;
-}
-
-export function getNccsApiSettings() {
- return {
- apiMode: extension_settings[extensionName]?.nccsApiMode || 'openai_test',
- apiUrl: extension_settings[extensionName]?.nccsApiUrl?.trim() || '',
- apiKey: extension_settings[extensionName]?.nccsApiKey?.trim() || '',
- model: extension_settings[extensionName]?.nccsModel || '',
- maxTokens: extension_settings[extensionName]?.nccsMaxTokens || 4000,
- temperature: extension_settings[extensionName]?.nccsTemperature || 0.7,
- tavernProfile: extension_settings[extensionName]?.nccsTavernProfile || ''
- };
-}
-
-export async function callNccsAI(messages, options = {}) {
- if (window.AMILY2_SYSTEM_PARALYZED === true) {
- console.error("[Amily2-Nccs制裁] 系统完整性已受损,所有外交活动被无限期中止。");
- return null;
- }
-
- const apiSettings = getNccsApiSettings();
-
- const finalOptions = {
- maxTokens: apiSettings.maxTokens,
- temperature: apiSettings.temperature,
- model: apiSettings.model,
- apiUrl: apiSettings.apiUrl,
- apiKey: apiSettings.apiKey,
- apiMode: apiSettings.apiMode,
- tavernProfile: apiSettings.tavernProfile,
- ...options
- };
-
- if (finalOptions.apiMode !== 'sillytavern_preset') {
- if (!finalOptions.apiUrl || !finalOptions.model || !finalOptions.apiKey) {
- console.warn("[Amily2-Nccs外交部] API配置不完整,无法调用AI");
- toastr.error("API配置不完整,请检查URL、Key和模型配置。", "Nccs-外交部");
- return null;
- }
- }
-
- console.groupCollapsed(`[Amily2号-Nccs统一API调用] ${new Date().toLocaleTimeString()}`);
- console.log("【请求参数】:", {
- mode: finalOptions.apiMode,
- model: finalOptions.model,
- maxTokens: finalOptions.maxTokens,
- temperature: finalOptions.temperature,
- messagesCount: messages.length
- });
- console.log("【消息内容】:", messages);
- console.groupEnd();
-
- try {
- let responseContent;
-
- switch (finalOptions.apiMode) {
- case 'openai_test':
- responseContent = await callNccsOpenAITest(messages, finalOptions);
- break;
- case 'sillytavern_preset':
- responseContent = await callNccsSillyTavernPreset(messages, finalOptions);
- break;
- default:
- console.error(`[Amily2-Nccs外交部] 未支持的API模式: ${finalOptions.apiMode}`);
- return null;
- }
-
- if (!responseContent) {
- console.warn('[Amily2-Nccs外交部] 未能获取AI响应内容');
- return null;
- }
-
- console.groupCollapsed("[Amily2号-Nccs AI回复]");
- console.log(responseContent);
- console.groupEnd();
-
- return responseContent;
-
- } catch (error) {
- console.error(`[Amily2-Nccs外交部] API调用发生错误:`, error);
-
- if (error.message.includes('400')) {
- toastr.error(`API请求格式错误 (400): 请检查消息格式和模型配置`, "Nccs API调用失败");
- } else if (error.message.includes('401')) {
- toastr.error(`API认证失败 (401): 请检查API Key配置`, "Nccs API调用失败");
- } else if (error.message.includes('403')) {
- toastr.error(`API访问被拒绝 (403): 请检查权限设置`, "Nccs API调用失败");
- } else if (error.message.includes('429')) {
- toastr.error(`API调用频率超限 (429): 请稍后重试`, "Nccs API调用失败");
- } else if (error.message.includes('500')) {
- toastr.error(`API服务器错误 (500): 请稍后重试`, "Nccs API调用失败");
- } else {
- toastr.error(`API调用失败: ${error.message}`, "Nccs API调用失败");
- }
-
- return null;
- }
-}
-
-async function callNccsOpenAITest(messages, options) {
- const isGoogleApi = options.apiUrl.includes('googleapis.com');
-
- const body = {
- chat_completion_source: 'openai',
- messages: messages,
- model: options.model,
- reverse_proxy: options.apiUrl,
- proxy_password: options.apiKey,
- stream: false,
- max_tokens: options.maxTokens || 30000,
- temperature: options.temperature || 1,
- top_p: options.top_p || 1,
- };
-
- if (!isGoogleApi) {
- Object.assign(body, {
- custom_prompt_post_processing: 'strict',
- enable_web_search: false,
- frequency_penalty: 0,
- group_names: [],
- include_reasoning: false,
- presence_penalty: 0.12,
- reasoning_effort: 'medium',
- request_images: false,
- });
- }
-
- const response = await fetch('/api/backends/chat-completions/generate', {
- method: 'POST',
- headers: { ...getRequestHeaders(), 'Content-Type': 'application/json' },
- body: JSON.stringify(body)
- });
-
- if (!response.ok) {
- const errorText = await response.text();
- throw new Error(`Nccs全兼容API请求失败: ${response.status} - ${errorText}`);
- }
-
- const responseData = await response.json();
- return responseData?.choices?.[0]?.message?.content;
-}
-
-async function callNccsSillyTavernPreset(messages, options) {
- console.log('[Amily2号-NccsST预设] 使用SillyTavern预设调用');
-
- if (!window.TavernHelper || !window.TavernHelper.triggerSlash) {
- throw new Error('TavernHelper不可用,无法使用SillyTavern预设模式');
- }
-
- const context = getContext();
- if (!context) {
- throw new Error('无法获取SillyTavern上下文');
- }
-
- const profileId = options.tavernProfile;
- if (!profileId) {
- throw new Error('未配置SillyTavern预设ID');
- }
-
- let originalProfile = '';
- let responsePromise;
-
- try {
- originalProfile = await window.TavernHelper.triggerSlash('/profile');
- console.log(`[Amily2号-NccsST预设] 当前配置文件: ${originalProfile}`);
-
- const targetProfile = context.extensionSettings?.connectionManager?.profiles?.find(p => p.id === profileId);
- if (!targetProfile) {
- throw new Error(`未找到配置文件ID: ${profileId}`);
- }
-
- const targetProfileName = targetProfile.name;
- console.log(`[Amily2号-NccsST预设] 目标配置文件: ${targetProfileName}`);
-
- const currentProfile = await window.TavernHelper.triggerSlash('/profile');
- if (currentProfile !== targetProfileName) {
- console.log(`[Amily2号-NccsST预设] 切换配置文件: ${currentProfile} -> ${targetProfileName}`);
- const escapedProfileName = targetProfileName.replace(/"/g, '\\"');
- await window.TavernHelper.triggerSlash(`/profile await=true "${escapedProfileName}"`);
- }
-
- if (!context.ConnectionManagerRequestService) {
- throw new Error('ConnectionManagerRequestService不可用');
- }
-
- console.log(`[Amily2号-NccsST预设] 通过配置文件 ${targetProfileName} 发送请求`);
- responsePromise = context.ConnectionManagerRequestService.sendRequest(
- targetProfile.id,
- messages,
- options.maxTokens || 4000
- );
-
- } finally {
- try {
- const currentProfileAfterCall = await window.TavernHelper.triggerSlash('/profile');
- if (originalProfile && originalProfile !== currentProfileAfterCall) {
- console.log(`[Amily2号-NccsST预设] 恢复原始配置文件: ${currentProfileAfterCall} -> ${originalProfile}`);
- const escapedOriginalProfile = originalProfile.replace(/"/g, '\\"');
- await window.TavernHelper.triggerSlash(`/profile await=true "${escapedOriginalProfile}"`);
- }
- } catch (restoreError) {
- console.error('[Amily2号-NccsST预设] 恢复配置文件失败:', restoreError);
- }
- }
-
- const result = await responsePromise;
-
- if (!result) {
- throw new Error('未收到API响应');
- }
-
- const normalizedResult = normalizeApiResponse(result);
- if (normalizedResult.error) {
- throw new Error(normalizedResult.error.message || 'SillyTavern预设API调用失败');
- }
-
- return normalizedResult.content;
-}
-
-export async function fetchNccsModels() {
- console.log('[Amily2号-Nccs外交部] 开始获取模型列表');
-
- const apiSettings = getNccsApiSettings();
-
- try {
- if (apiSettings.apiMode === 'sillytavern_preset') {
- // SillyTavern预设模式:获取当前预设的模型
- const context = getContext();
- if (!context?.extensionSettings?.connectionManager?.profiles) {
- throw new Error('无法获取SillyTavern配置文件列表');
- }
-
- const targetProfile = context.extensionSettings.connectionManager.profiles.find(p => p.id === apiSettings.tavernProfile);
- if (!targetProfile) {
- throw new Error(`未找到配置文件ID: ${apiSettings.tavernProfile}`);
- }
-
- const models = [];
- if (targetProfile.openai_model) {
- models.push({ id: targetProfile.openai_model, name: targetProfile.openai_model });
- }
-
- if (models.length === 0) {
- throw new Error('当前预设未配置模型');
- }
-
- console.log('[Amily2号-Nccs外交部] SillyTavern预设模式获取到模型:', models);
- return models;
-
- } else {
- if (!apiSettings.apiUrl || !apiSettings.apiKey) {
- throw new Error('API URL或Key未配置');
- }
-
- const response = await fetch('/api/backends/chat-completions/status', {
- method: 'POST',
- headers: {
- ...getRequestHeaders(),
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- reverse_proxy: apiSettings.apiUrl,
- proxy_password: apiSettings.apiKey,
- chat_completion_source: 'openai'
- })
- });
-
- if (!response.ok) {
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
- }
-
- const rawData = await response.json();
- const models = Array.isArray(rawData) ? rawData : (rawData.data || rawData.models || []);
-
- if (!Array.isArray(models)) {
- const errorMessage = rawData.error?.message || 'API未返回有效的模型列表数组';
- throw new Error(errorMessage);
- }
-
- const formattedModels = models
- .map(m => {
- // 从name字段中提取模型名称,去掉"models/"前缀
- const modelIdRaw = m.name || m.id || m.model || m;
- const modelName = String(modelIdRaw).replace(/^models\//, '');
- return {
- id: modelName,
- name: modelName
- };
- })
- .filter(m => m.id)
- .sort((a, b) => String(a.name).localeCompare(String(b.name)));
-
- console.log('[Amily2号-Nccs外交部] 全兼容模式获取到模型:', formattedModels);
- return formattedModels;
- }
- } catch (error) {
- console.error('[Amily2号-Nccs外交部] 获取模型列表失败:', error);
- toastr.error(`获取模型列表失败: ${error.message}`, 'Nccs API');
- throw error;
- }
-}
-
-export async function testNccsApiConnection() {
- console.log('[Amily2号-Nccs外交部] 开始API连接测试');
-
- const apiSettings = getNccsApiSettings();
-
- if (apiSettings.apiMode === 'sillytavern_preset') {
- if (!apiSettings.tavernProfile) {
- toastr.error('未配置SillyTavern预设ID', 'Nccs API连接测试失败');
- return false;
- }
- } else {
- if (!apiSettings.apiUrl || !apiSettings.apiKey || !apiSettings.model) {
- toastr.error('API配置不完整,请检查URL、Key和模型', 'Nccs API连接测试失败');
- return false;
- }
- }
-
- try {
- toastr.info('正在发送测试消息"你好!"...', 'Nccs API连接测试');
-
- const userName = window.SillyTavern.getContext?.()?.name1 || '用户';
- const systemPrompt = `接下来用户会使用测试按钮测试api连接是否正常,请回复ta连接是正常的,称呼用户为:“${userName}大人”,并复述群号1060183271,告知ta,本扩展开发者:“诗与酒.”正静待ta的入驻。`;
-
- const testMessages = [
- { role: 'system', content: systemPrompt },
- { role: 'user', content: '你好!' }
- ];
-
- const response = await callNccsAI(testMessages);
-
- if (response && response.trim()) {
- console.log('[Amily2号-Nccs外交部] 测试消息响应:', response);
- const formattedResponse = response.replace(/\*\*(.*?)\*\*/g, '
$1');
- toastr.success(`连接测试成功!AI回复: "${formattedResponse}"`, 'Nccs API连接测试成功', { "escapeHtml": false });
- return true;
- } else {
- throw new Error('API未返回有效响应');
- }
-
- } catch (error) {
- console.error('[Amily2号-Nccs外交部] 连接测试失败:', error);
- toastr.error(`连接测试失败: ${error.message}`, 'Nccs API连接测试失败');
- return false;
- }
-}
+import { extension_settings, getContext } from "/scripts/extensions.js";
+import { characters, this_chid, getRequestHeaders, saveSettingsDebounced, eventSource, event_types } from "/script.js";
+import { extensionName } from "../../utils/settings.js";
+import { amilyHelper } from '../../core/tavern-helper/main.js';
+
+let ChatCompletionService = undefined;
+try {
+ const module = await import('/scripts/custom-request.js');
+ ChatCompletionService = module.ChatCompletionService;
+ console.log('[Amily2号-Nccs外交部] 已成功召唤"皇家信使"(ChatCompletionService)。');
+} catch (e) {
+ console.warn("[Amily2号-Nccs外交部] 未能召唤“皇家信使”,部分高级功能(如Claw代理)将受限。请考虑更新SillyTavern版本。", e);
+}
+
+function normalizeApiResponse(responseData) {
+ let data = responseData;
+ if (typeof data === 'string') {
+ try {
+ data = JSON.parse(data);
+ } catch (e) {
+ console.error(`[${extensionName}] Nccs API响应JSON解析失败:`, e);
+ return { error: { message: 'Invalid JSON response' } };
+ }
+ }
+ if (data && typeof data.data === 'object' && data.data !== null && !Array.isArray(data.data)) {
+ if (Object.hasOwn(data.data, 'data')) {
+ data = data.data;
+ }
+ }
+ if (data && data.choices && data.choices[0]) {
+ return { content: data.choices[0].message?.content?.trim() };
+ }
+ if (data && data.content) {
+ return { content: data.content.trim() };
+ }
+ if (data && data.data) {
+ return { data: data.data };
+ }
+ if (data && data.error) {
+ return { error: data.error };
+ }
+ return data;
+}
+
+export function getNccsApiSettings() {
+ return {
+ apiMode: extension_settings[extensionName]?.nccsApiMode || 'openai_test',
+ apiUrl: extension_settings[extensionName]?.nccsApiUrl?.trim() || '',
+ apiKey: extension_settings[extensionName]?.nccsApiKey?.trim() || '',
+ model: extension_settings[extensionName]?.nccsModel || '',
+ maxTokens: extension_settings[extensionName]?.nccsMaxTokens || 4000,
+ temperature: extension_settings[extensionName]?.nccsTemperature || 0.7,
+ tavernProfile: extension_settings[extensionName]?.nccsTavernProfile || ''
+ };
+}
+
+export async function callNccsAI(messages, options = {}) {
+ if (window.AMILY2_SYSTEM_PARALYZED === true) {
+ console.error("[Amily2-Nccs制裁] 系统完整性已受损,所有外交活动被无限期中止。");
+ return null;
+ }
+
+ const apiSettings = getNccsApiSettings();
+
+ const finalOptions = {
+ maxTokens: apiSettings.maxTokens,
+ temperature: apiSettings.temperature,
+ model: apiSettings.model,
+ apiUrl: apiSettings.apiUrl,
+ apiKey: apiSettings.apiKey,
+ apiMode: apiSettings.apiMode,
+ tavernProfile: apiSettings.tavernProfile,
+ ...options
+ };
+
+ if (finalOptions.apiMode !== 'sillytavern_preset') {
+ if (!finalOptions.apiUrl || !finalOptions.model || !finalOptions.apiKey) {
+ console.warn("[Amily2-Nccs外交部] API配置不完整,无法调用AI");
+ toastr.error("API配置不完整,请检查URL、Key和模型配置。", "Nccs-外交部");
+ return null;
+ }
+ }
+
+ console.groupCollapsed(`[Amily2号-Nccs统一API调用] ${new Date().toLocaleTimeString()}`);
+ console.log("【请求参数】:", {
+ mode: finalOptions.apiMode,
+ model: finalOptions.model,
+ maxTokens: finalOptions.maxTokens,
+ temperature: finalOptions.temperature,
+ messagesCount: messages.length
+ });
+ console.log("【消息内容】:", messages);
+ console.groupEnd();
+
+ try {
+ let responseContent;
+
+ switch (finalOptions.apiMode) {
+ case 'openai_test':
+ responseContent = await callNccsOpenAITest(messages, finalOptions);
+ break;
+ case 'sillytavern_preset':
+ responseContent = await callNccsSillyTavernPreset(messages, finalOptions);
+ break;
+ default:
+ console.error(`[Amily2-Nccs外交部] 未支持的API模式: ${finalOptions.apiMode}`);
+ return null;
+ }
+
+ if (!responseContent) {
+ console.warn('[Amily2-Nccs外交部] 未能获取AI响应内容');
+ return null;
+ }
+
+ console.groupCollapsed("[Amily2号-Nccs AI回复]");
+ console.log(responseContent);
+ console.groupEnd();
+
+ return responseContent;
+
+ } catch (error) {
+ console.error(`[Amily2-Nccs外交部] API调用发生错误:`, error);
+
+ if (error.message.includes('400')) {
+ toastr.error(`API请求格式错误 (400): 请检查消息格式和模型配置`, "Nccs API调用失败");
+ } else if (error.message.includes('401')) {
+ toastr.error(`API认证失败 (401): 请检查API Key配置`, "Nccs API调用失败");
+ } else if (error.message.includes('403')) {
+ toastr.error(`API访问被拒绝 (403): 请检查权限设置`, "Nccs API调用失败");
+ } else if (error.message.includes('429')) {
+ toastr.error(`API调用频率超限 (429): 请稍后重试`, "Nccs API调用失败");
+ } else if (error.message.includes('500')) {
+ toastr.error(`API服务器错误 (500): 请稍后重试`, "Nccs API调用失败");
+ } else {
+ toastr.error(`API调用失败: ${error.message}`, "Nccs API调用失败");
+ }
+
+ return null;
+ }
+}
+
+async function callNccsOpenAITest(messages, options) {
+ const isGoogleApi = options.apiUrl.includes('googleapis.com');
+
+ const body = {
+ chat_completion_source: 'openai',
+ messages: messages,
+ model: options.model,
+ reverse_proxy: options.apiUrl,
+ proxy_password: options.apiKey,
+ stream: false,
+ max_tokens: options.maxTokens || 30000,
+ temperature: options.temperature || 1,
+ top_p: options.top_p || 1,
+ };
+
+ if (!isGoogleApi) {
+ Object.assign(body, {
+ custom_prompt_post_processing: 'strict',
+ enable_web_search: false,
+ frequency_penalty: 0,
+ group_names: [],
+ include_reasoning: false,
+ presence_penalty: 0.12,
+ reasoning_effort: 'medium',
+ request_images: false,
+ });
+ }
+
+ const response = await fetch('/api/backends/chat-completions/generate', {
+ method: 'POST',
+ headers: { ...getRequestHeaders(), 'Content-Type': 'application/json' },
+ body: JSON.stringify(body)
+ });
+
+ if (!response.ok) {
+ const errorText = await response.text();
+ throw new Error(`Nccs全兼容API请求失败: ${response.status} - ${errorText}`);
+ }
+
+ const responseData = await response.json();
+ return responseData?.choices?.[0]?.message?.content;
+}
+
+async function callNccsSillyTavernPreset(messages, options) {
+ console.log('[Amily2号-NccsST预设] 使用SillyTavern预设调用');
+
+ const context = getContext();
+ if (!context) {
+ throw new Error('无法获取SillyTavern上下文');
+ }
+
+ const profileId = options.tavernProfile;
+ if (!profileId) {
+ throw new Error('未配置SillyTavern预设ID');
+ }
+
+ let originalProfile = '';
+ let responsePromise;
+
+ try {
+ originalProfile = await amilyHelper.triggerSlash('/profile');
+ console.log(`[Amily2号-NccsST预设] 当前配置文件: ${originalProfile}`);
+
+ const targetProfile = context.extensionSettings?.connectionManager?.profiles?.find(p => p.id === profileId);
+ if (!targetProfile) {
+ throw new Error(`未找到配置文件ID: ${profileId}`);
+ }
+
+ const targetProfileName = targetProfile.name;
+ console.log(`[Amily2号-NccsST预设] 目标配置文件: ${targetProfileName}`);
+
+ const currentProfile = await amilyHelper.triggerSlash('/profile');
+ if (currentProfile !== targetProfileName) {
+ console.log(`[Amily2号-NccsST预设] 切换配置文件: ${currentProfile} -> ${targetProfileName}`);
+ const escapedProfileName = targetProfileName.replace(/"/g, '\\"');
+ await amilyHelper.triggerSlash(`/profile await=true "${escapedProfileName}"`);
+ }
+
+ if (!context.ConnectionManagerRequestService) {
+ throw new Error('ConnectionManagerRequestService不可用');
+ }
+
+ console.log(`[Amily2号-NccsST预设] 通过配置文件 ${targetProfileName} 发送请求`);
+ responsePromise = context.ConnectionManagerRequestService.sendRequest(
+ targetProfile.id,
+ messages,
+ options.maxTokens || 4000
+ );
+
+ } finally {
+ try {
+ const currentProfileAfterCall = await amilyHelper.triggerSlash('/profile');
+ if (originalProfile && originalProfile !== currentProfileAfterCall) {
+ console.log(`[Amily2号-NccsST预设] 恢复原始配置文件: ${currentProfileAfterCall} -> ${originalProfile}`);
+ const escapedOriginalProfile = originalProfile.replace(/"/g, '\\"');
+ await amilyHelper.triggerSlash(`/profile await=true "${escapedOriginalProfile}"`);
+ }
+ } catch (restoreError) {
+ console.error('[Amily2号-NccsST预设] 恢复配置文件失败:', restoreError);
+ }
+ }
+
+ const result = await responsePromise;
+
+ if (!result) {
+ throw new Error('未收到API响应');
+ }
+
+ const normalizedResult = normalizeApiResponse(result);
+ if (normalizedResult.error) {
+ throw new Error(normalizedResult.error.message || 'SillyTavern预设API调用失败');
+ }
+
+ return normalizedResult.content;
+}
+
+export async function fetchNccsModels() {
+ console.log('[Amily2号-Nccs外交部] 开始获取模型列表');
+
+ const apiSettings = getNccsApiSettings();
+
+ try {
+ if (apiSettings.apiMode === 'sillytavern_preset') {
+ // SillyTavern预设模式:获取当前预设的模型
+ const context = getContext();
+ if (!context?.extensionSettings?.connectionManager?.profiles) {
+ throw new Error('无法获取SillyTavern配置文件列表');
+ }
+
+ const targetProfile = context.extensionSettings.connectionManager.profiles.find(p => p.id === apiSettings.tavernProfile);
+ if (!targetProfile) {
+ throw new Error(`未找到配置文件ID: ${apiSettings.tavernProfile}`);
+ }
+
+ const models = [];
+ if (targetProfile.openai_model) {
+ models.push({ id: targetProfile.openai_model, name: targetProfile.openai_model });
+ }
+
+ if (models.length === 0) {
+ throw new Error('当前预设未配置模型');
+ }
+
+ console.log('[Amily2号-Nccs外交部] SillyTavern预设模式获取到模型:', models);
+ return models;
+
+ } else {
+ if (!apiSettings.apiUrl || !apiSettings.apiKey) {
+ throw new Error('API URL或Key未配置');
+ }
+
+ const response = await fetch('/api/backends/chat-completions/status', {
+ method: 'POST',
+ headers: {
+ ...getRequestHeaders(),
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ reverse_proxy: apiSettings.apiUrl,
+ proxy_password: apiSettings.apiKey,
+ chat_completion_source: 'openai'
+ })
+ });
+
+ if (!response.ok) {
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
+ }
+
+ const rawData = await response.json();
+ const models = Array.isArray(rawData) ? rawData : (rawData.data || rawData.models || []);
+
+ if (!Array.isArray(models)) {
+ const errorMessage = rawData.error?.message || 'API未返回有效的模型列表数组';
+ throw new Error(errorMessage);
+ }
+
+ const formattedModels = models
+ .map(m => {
+ // 从name字段中提取模型名称,去掉"models/"前缀
+ const modelIdRaw = m.name || m.id || m.model || m;
+ const modelName = String(modelIdRaw).replace(/^models\//, '');
+ return {
+ id: modelName,
+ name: modelName
+ };
+ })
+ .filter(m => m.id)
+ .sort((a, b) => String(a.name).localeCompare(String(b.name)));
+
+ console.log('[Amily2号-Nccs外交部] 全兼容模式获取到模型:', formattedModels);
+ return formattedModels;
+ }
+ } catch (error) {
+ console.error('[Amily2号-Nccs外交部] 获取模型列表失败:', error);
+ toastr.error(`获取模型列表失败: ${error.message}`, 'Nccs API');
+ throw error;
+ }
+}
+
+export async function testNccsApiConnection() {
+ console.log('[Amily2号-Nccs外交部] 开始API连接测试');
+
+ const apiSettings = getNccsApiSettings();
+
+ if (apiSettings.apiMode === 'sillytavern_preset') {
+ if (!apiSettings.tavernProfile) {
+ toastr.error('未配置SillyTavern预设ID', 'Nccs API连接测试失败');
+ return false;
+ }
+ } else {
+ if (!apiSettings.apiUrl || !apiSettings.apiKey || !apiSettings.model) {
+ toastr.error('API配置不完整,请检查URL、Key和模型', 'Nccs API连接测试失败');
+ return false;
+ }
+ }
+
+ try {
+ toastr.info('正在发送测试消息"你好!"...', 'Nccs API连接测试');
+
+ const userName = window.SillyTavern.getContext?.()?.name1 || '用户';
+ const systemPrompt = `接下来用户会使用测试按钮测试api连接是否正常,请回复ta连接是正常的,称呼用户为:“${userName}大人”,并复述群号1060183271,告知ta,本扩展开发者:“诗与酒.”正静待ta的入驻。`;
+
+ const testMessages = [
+ { role: 'system', content: systemPrompt },
+ { role: 'user', content: '你好!' }
+ ];
+
+ const response = await callNccsAI(testMessages);
+
+ if (response && response.trim()) {
+ console.log('[Amily2号-Nccs外交部] 测试消息响应:', response);
+ const formattedResponse = response.replace(/\*\*(.*?)\*\*/g, '
$1');
+ toastr.success(`连接测试成功!AI回复: "${formattedResponse}"`, 'Nccs API连接测试成功', { "escapeHtml": false });
+ return true;
+ } else {
+ throw new Error('API未返回有效响应');
+ }
+
+ } catch (error) {
+ console.error('[Amily2号-Nccs外交部] 连接测试失败:', error);
+ toastr.error(`连接测试失败: ${error.message}`, 'Nccs API连接测试失败');
+ return false;
+ }
+}
diff --git a/core/api/Ngms_api.js b/core/api/Ngms_api.js
index 66b103c..bd97c58 100644
--- a/core/api/Ngms_api.js
+++ b/core/api/Ngms_api.js
@@ -1,388 +1,385 @@
-import { extension_settings, getContext } from "/scripts/extensions.js";
-import { characters, this_chid, getRequestHeaders, saveSettingsDebounced, eventSource, event_types } from "/script.js";
-import { extensionName } from "../../utils/settings.js";
-
-let ChatCompletionService = undefined;
-try {
- const module = await import('/scripts/custom-request.js');
- ChatCompletionService = module.ChatCompletionService;
- console.log('[Amily2号-Ngms外交部] 已成功召唤"皇家信使"(ChatCompletionService)。');
-} catch (e) {
- console.warn("[Amily2号-Ngms外交部] 未能召唤“皇家信使”,部分高级功能(如Claw代理)将受限。请考虑更新SillyTavern版本。", e);
-}
-
-function normalizeApiResponse(responseData) {
- let data = responseData;
- if (typeof data === 'string') {
- try {
- data = JSON.parse(data);
- } catch (e) {
- console.error(`[${extensionName}] Ngms API响应JSON解析失败:`, e);
- return { error: { message: 'Invalid JSON response' } };
- }
- }
- if (data && typeof data.data === 'object' && data.data !== null && !Array.isArray(data.data)) {
- if (Object.hasOwn(data.data, 'data')) {
- data = data.data;
- }
- }
- if (data && data.choices && data.choices[0]) {
- return { content: data.choices[0].message?.content?.trim() };
- }
- if (data && data.content) {
- return { content: data.content.trim() };
- }
- if (data && data.data) {
- return { data: data.data };
- }
- if (data && data.error) {
- return { error: data.error };
- }
- return data;
-}
-
-export function getNgmsApiSettings() {
- return {
- apiMode: extension_settings[extensionName]?.ngmsApiMode || 'openai_test',
- apiUrl: extension_settings[extensionName]?.ngmsApiUrl?.trim() || '',
- apiKey: extension_settings[extensionName]?.ngmsApiKey?.trim() || '',
- model: extension_settings[extensionName]?.ngmsModel || '',
- maxTokens: extension_settings[extensionName]?.ngmsMaxTokens || 4000,
- temperature: extension_settings[extensionName]?.ngmsTemperature || 0.7,
- tavernProfile: extension_settings[extensionName]?.ngmsTavernProfile || ''
- };
-}
-
-export async function callNgmsAI(messages, options = {}) {
- if (window.AMILY2_SYSTEM_PARALYZED === true) {
- console.error("[Amily2-Ngms制裁] 系统完整性已受损,所有外交活动被无限期中止。");
- return null;
- }
-
- const apiSettings = getNgmsApiSettings();
-
- const finalOptions = {
- maxTokens: apiSettings.maxTokens,
- temperature: apiSettings.temperature,
- model: apiSettings.model,
- apiUrl: apiSettings.apiUrl,
- apiKey: apiSettings.apiKey,
- apiMode: apiSettings.apiMode,
- tavernProfile: apiSettings.tavernProfile,
- ...options
- };
-
- if (finalOptions.apiMode !== 'sillytavern_preset') {
- if (!finalOptions.apiUrl || !finalOptions.model || !finalOptions.apiKey) {
- console.warn("[Amily2-Ngms外交部] API配置不完整,无法调用AI");
- toastr.error("API配置不完整,请检查URL、Key和模型配置。", "Ngms-外交部");
- return null;
- }
- }
-
- console.groupCollapsed(`[Amily2号-Ngms统一API调用] ${new Date().toLocaleTimeString()}`);
- console.log("【请求参数】:", {
- mode: finalOptions.apiMode,
- model: finalOptions.model,
- maxTokens: finalOptions.maxTokens,
- temperature: finalOptions.temperature,
- messagesCount: messages.length
- });
- console.log("【消息内容】:", messages);
- console.groupEnd();
-
- try {
- let responseContent;
-
- switch (finalOptions.apiMode) {
- case 'openai_test':
- responseContent = await callNgmsOpenAITest(messages, finalOptions);
- break;
- case 'sillytavern_preset':
- responseContent = await callNgmsSillyTavernPreset(messages, finalOptions);
- break;
- default:
- console.error(`[Amily2-Ngms外交部] 未支持的API模式: ${finalOptions.apiMode}`);
- return null;
- }
-
- if (!responseContent) {
- console.warn('[Amily2-Ngms外交部] 未能获取AI响应内容');
- return null;
- }
-
- console.groupCollapsed("[Amily2号-Ngms AI回复]");
- console.log(responseContent);
- console.groupEnd();
-
- return responseContent;
-
- } catch (error) {
- console.error(`[Amily2-Ngms外交部] API调用发生错误:`, error);
-
- if (error.message.includes('400')) {
- toastr.error(`API请求格式错误 (400): 请检查消息格式和模型配置`, "Ngms API调用失败");
- } else if (error.message.includes('401')) {
- toastr.error(`API认证失败 (401): 请检查API Key配置`, "Ngms API调用失败");
- } else if (error.message.includes('403')) {
- toastr.error(`API访问被拒绝 (403): 请检查权限设置`, "Ngms API调用失败");
- } else if (error.message.includes('429')) {
- toastr.error(`API调用频率超限 (429): 请稍后重试`, "Ngms API调用失败");
- } else if (error.message.includes('500')) {
- toastr.error(`API服务器错误 (500): 请稍后重试`, "Ngms API调用失败");
- } else {
- toastr.error(`API调用失败: ${error.message}`, "Ngms API调用失败");
- }
-
- return null;
- }
-}
-
-async function callNgmsOpenAITest(messages, options) {
- const isGoogleApi = options.apiUrl.includes('googleapis.com');
-
- const body = {
- chat_completion_source: 'openai',
- messages: messages,
- model: options.model,
- reverse_proxy: options.apiUrl,
- proxy_password: options.apiKey,
- stream: false,
- max_tokens: options.maxTokens || 30000,
- temperature: options.temperature || 1,
- top_p: options.top_p || 1,
- };
-
- if (!isGoogleApi) {
- Object.assign(body, {
- custom_prompt_post_processing: 'strict',
- enable_web_search: false,
- frequency_penalty: 0,
- group_names: [],
- include_reasoning: false,
- presence_penalty: 0.12,
- reasoning_effort: 'medium',
- request_images: false,
- });
- }
-
- const response = await fetch('/api/backends/chat-completions/generate', {
- method: 'POST',
- headers: { ...getRequestHeaders(), 'Content-Type': 'application/json' },
- body: JSON.stringify(body)
- });
-
- if (!response.ok) {
- const errorText = await response.text();
- throw new Error(`Ngms全兼容API请求失败: ${response.status} - ${errorText}`);
- }
-
- const responseData = await response.json();
- return responseData?.choices?.[0]?.message?.content;
-}
-
-async function callNgmsSillyTavernPreset(messages, options) {
- console.log('[Amily2号-NgmsST预设] 使用SillyTavern预设调用');
-
- if (!window.TavernHelper || !window.TavernHelper.triggerSlash) {
- throw new Error('TavernHelper不可用,无法使用SillyTavern预设模式');
- }
-
- const context = getContext();
- if (!context) {
- throw new Error('无法获取SillyTavern上下文');
- }
-
- const profileId = options.tavernProfile;
- if (!profileId) {
- throw new Error('未配置SillyTavern预设ID');
- }
-
- let originalProfile = '';
- let responsePromise;
-
- try {
- originalProfile = await window.TavernHelper.triggerSlash('/profile');
- console.log(`[Amily2号-NgmsST预设] 当前配置文件: ${originalProfile}`);
-
- const targetProfile = context.extensionSettings?.connectionManager?.profiles?.find(p => p.id === profileId);
- if (!targetProfile) {
- throw new Error(`未找到配置文件ID: ${profileId}`);
- }
-
- const targetProfileName = targetProfile.name;
- console.log(`[Amily2号-NgmsST预设] 目标配置文件: ${targetProfileName}`);
-
- const currentProfile = await window.TavernHelper.triggerSlash('/profile');
- if (currentProfile !== targetProfileName) {
- console.log(`[Amily2号-NgmsST预设] 切换配置文件: ${currentProfile} -> ${targetProfileName}`);
- const escapedProfileName = targetProfileName.replace(/"/g, '\\"');
- await window.TavernHelper.triggerSlash(`/profile await=true "${escapedProfileName}"`);
- }
-
- if (!context.ConnectionManagerRequestService) {
- throw new Error('ConnectionManagerRequestService不可用');
- }
-
- console.log(`[Amily2号-NgmsST预设] 通过配置文件 ${targetProfileName} 发送请求`);
- responsePromise = context.ConnectionManagerRequestService.sendRequest(
- targetProfile.id,
- messages,
- options.maxTokens || 4000
- );
-
- } finally {
- try {
- const currentProfileAfterCall = await window.TavernHelper.triggerSlash('/profile');
- if (originalProfile && originalProfile !== currentProfileAfterCall) {
- console.log(`[Amily2号-NgmsST预设] 恢复原始配置文件: ${currentProfileAfterCall} -> ${originalProfile}`);
- const escapedOriginalProfile = originalProfile.replace(/"/g, '\\"');
- await window.TavernHelper.triggerSlash(`/profile await=true "${escapedOriginalProfile}"`);
- }
- } catch (restoreError) {
- console.error('[Amily2号-NgmsST预设] 恢复配置文件失败:', restoreError);
- }
- }
-
- const result = await responsePromise;
-
- if (!result) {
- throw new Error('未收到API响应');
- }
-
- const normalizedResult = normalizeApiResponse(result);
- if (normalizedResult.error) {
- throw new Error(normalizedResult.error.message || 'SillyTavern预设API调用失败');
- }
-
- return normalizedResult.content;
-}
-
-export async function fetchNgmsModels() {
- console.log('[Amily2号-Ngms外交部] 开始获取模型列表');
-
- const apiSettings = getNgmsApiSettings();
-
- try {
- if (apiSettings.apiMode === 'sillytavern_preset') {
- // SillyTavern预设模式:获取当前预设的模型
- const context = getContext();
- if (!context?.extensionSettings?.connectionManager?.profiles) {
- throw new Error('无法获取SillyTavern配置文件列表');
- }
-
- const targetProfile = context.extensionSettings.connectionManager.profiles.find(p => p.id === apiSettings.tavernProfile);
- if (!targetProfile) {
- throw new Error(`未找到配置文件ID: ${apiSettings.tavernProfile}`);
- }
-
- const models = [];
- if (targetProfile.openai_model) {
- models.push({ id: targetProfile.openai_model, name: targetProfile.openai_model });
- }
-
- if (models.length === 0) {
- throw new Error('当前预设未配置模型');
- }
-
- console.log('[Amily2号-Ngms外交部] SillyTavern预设模式获取到模型:', models);
- return models;
-
- } else {
- if (!apiSettings.apiUrl || !apiSettings.apiKey) {
- throw new Error('API URL或Key未配置');
- }
-
- const response = await fetch('/api/backends/chat-completions/status', {
- method: 'POST',
- headers: {
- ...getRequestHeaders(),
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- reverse_proxy: apiSettings.apiUrl,
- proxy_password: apiSettings.apiKey,
- chat_completion_source: 'openai'
- })
- });
-
- if (!response.ok) {
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
- }
-
- const rawData = await response.json();
- const models = Array.isArray(rawData) ? rawData : (rawData.data || rawData.models || []);
-
- if (!Array.isArray(models)) {
- const errorMessage = result.error?.message || 'API未返回有效的模型列表数组';
- throw new Error(errorMessage);
- }
-
- const formattedModels = models
- .map(m => {
- // 从name字段中提取模型名称,去掉"models/"前缀
- const modelIdRaw = m.name || m.id || m.model || m;
- const modelName = String(modelIdRaw).replace(/^models\//, '');
- return {
- id: modelName,
- name: modelName
- };
- })
- .filter(m => m.id)
- .sort((a, b) => String(a.name).localeCompare(String(b.name)));
-
- console.log('[Amily2号-Ngms外交部] 全兼容模式获取到模型:', formattedModels);
- return formattedModels;
- }
- } catch (error) {
- console.error('[Amily2号-Ngms外交部] 获取模型列表失败:', error);
- toastr.error(`获取模型列表失败: ${error.message}`, 'Ngms API');
- throw error;
- }
-}
-
-export async function testNgmsApiConnection() {
- console.log('[Amily2号-Ngms外交部] 开始API连接测试');
-
- const apiSettings = getNgmsApiSettings();
-
- if (apiSettings.apiMode === 'sillytavern_preset') {
- if (!apiSettings.tavernProfile) {
- toastr.error('未配置SillyTavern预设ID', 'Ngms API连接测试失败');
- return false;
- }
- } else {
- if (!apiSettings.apiUrl || !apiSettings.apiKey || !apiSettings.model) {
- toastr.error('API配置不完整,请检查URL、Key和模型', 'Ngms API连接测试失败');
- return false;
- }
- }
-
- try {
- toastr.info('正在发送测试消息"你好!"...', 'Ngms API连接测试');
-
- const userName = window.SillyTavern.getContext?.()?.name1 || '用户';
- const systemPrompt = `接下来用户会使用测试按钮测试api连接是否正常,请回复ta连接是正常的,称呼用户为:“${userName}大人”,并复述群号1060183271,告知ta,本扩展开发者:“诗与酒.”正静待ta的入驻。`;
-
- const testMessages = [
- { role: 'system', content: systemPrompt },
- { role: 'user', content: '你好!' }
- ];
-
- const response = await callNgmsAI(testMessages);
-
- if (response && response.trim()) {
- console.log('[Amily2号-Ngms外交部] 测试消息响应:', response);
- const formattedResponse = response.replace(/\*\*(.*?)\*\*/g, '
$1');
- toastr.success(`连接测试成功!AI回复: "${formattedResponse}"`, 'Ngms API连接测试成功', { "escapeHtml": false });
- return true;
- } else {
- throw new Error('API未返回有效响应');
- }
-
- } catch (error) {
- console.error('[Amily2号-Ngms外交部] 连接测试失败:', error);
- toastr.error(`连接测试失败: ${error.message}`, 'Ngms API连接测试失败');
- return false;
- }
-}
+import { extension_settings, getContext } from "/scripts/extensions.js";
+import { characters, this_chid, getRequestHeaders, saveSettingsDebounced, eventSource, event_types } from "/script.js";
+import { extensionName } from "../../utils/settings.js";
+import { amilyHelper } from '../../core/tavern-helper/main.js';
+
+let ChatCompletionService = undefined;
+try {
+ const module = await import('/scripts/custom-request.js');
+ ChatCompletionService = module.ChatCompletionService;
+ console.log('[Amily2号-Ngms外交部] 已成功召唤"皇家信使"(ChatCompletionService)。');
+} catch (e) {
+ console.warn("[Amily2号-Ngms外交部] 未能召唤“皇家信使”,部分高级功能(如Claw代理)将受限。请考虑更新SillyTavern版本。", e);
+}
+
+function normalizeApiResponse(responseData) {
+ let data = responseData;
+ if (typeof data === 'string') {
+ try {
+ data = JSON.parse(data);
+ } catch (e) {
+ console.error(`[${extensionName}] Ngms API响应JSON解析失败:`, e);
+ return { error: { message: 'Invalid JSON response' } };
+ }
+ }
+ if (data && typeof data.data === 'object' && data.data !== null && !Array.isArray(data.data)) {
+ if (Object.hasOwn(data.data, 'data')) {
+ data = data.data;
+ }
+ }
+ if (data && data.choices && data.choices[0]) {
+ return { content: data.choices[0].message?.content?.trim() };
+ }
+ if (data && data.content) {
+ return { content: data.content.trim() };
+ }
+ if (data && data.data) {
+ return { data: data.data };
+ }
+ if (data && data.error) {
+ return { error: data.error };
+ }
+ return data;
+}
+
+export function getNgmsApiSettings() {
+ return {
+ apiMode: extension_settings[extensionName]?.ngmsApiMode || 'openai_test',
+ apiUrl: extension_settings[extensionName]?.ngmsApiUrl?.trim() || '',
+ apiKey: extension_settings[extensionName]?.ngmsApiKey?.trim() || '',
+ model: extension_settings[extensionName]?.ngmsModel || '',
+ maxTokens: extension_settings[extensionName]?.ngmsMaxTokens || 4000,
+ temperature: extension_settings[extensionName]?.ngmsTemperature || 0.7,
+ tavernProfile: extension_settings[extensionName]?.ngmsTavernProfile || ''
+ };
+}
+
+export async function callNgmsAI(messages, options = {}) {
+ if (window.AMILY2_SYSTEM_PARALYZED === true) {
+ console.error("[Amily2-Ngms制裁] 系统完整性已受损,所有外交活动被无限期中止。");
+ return null;
+ }
+
+ const apiSettings = getNgmsApiSettings();
+
+ const finalOptions = {
+ maxTokens: apiSettings.maxTokens,
+ temperature: apiSettings.temperature,
+ model: apiSettings.model,
+ apiUrl: apiSettings.apiUrl,
+ apiKey: apiSettings.apiKey,
+ apiMode: apiSettings.apiMode,
+ tavernProfile: apiSettings.tavernProfile,
+ ...options
+ };
+
+ if (finalOptions.apiMode !== 'sillytavern_preset') {
+ if (!finalOptions.apiUrl || !finalOptions.model || !finalOptions.apiKey) {
+ console.warn("[Amily2-Ngms外交部] API配置不完整,无法调用AI");
+ toastr.error("API配置不完整,请检查URL、Key和模型配置。", "Ngms-外交部");
+ return null;
+ }
+ }
+
+ console.groupCollapsed(`[Amily2号-Ngms统一API调用] ${new Date().toLocaleTimeString()}`);
+ console.log("【请求参数】:", {
+ mode: finalOptions.apiMode,
+ model: finalOptions.model,
+ maxTokens: finalOptions.maxTokens,
+ temperature: finalOptions.temperature,
+ messagesCount: messages.length
+ });
+ console.log("【消息内容】:", messages);
+ console.groupEnd();
+
+ try {
+ let responseContent;
+
+ switch (finalOptions.apiMode) {
+ case 'openai_test':
+ responseContent = await callNgmsOpenAITest(messages, finalOptions);
+ break;
+ case 'sillytavern_preset':
+ responseContent = await callNgmsSillyTavernPreset(messages, finalOptions);
+ break;
+ default:
+ console.error(`[Amily2-Ngms外交部] 未支持的API模式: ${finalOptions.apiMode}`);
+ return null;
+ }
+
+ if (!responseContent) {
+ console.warn('[Amily2-Ngms外交部] 未能获取AI响应内容');
+ return null;
+ }
+
+ console.groupCollapsed("[Amily2号-Ngms AI回复]");
+ console.log(responseContent);
+ console.groupEnd();
+
+ return responseContent;
+
+ } catch (error) {
+ console.error(`[Amily2-Ngms外交部] API调用发生错误:`, error);
+
+ if (error.message.includes('400')) {
+ toastr.error(`API请求格式错误 (400): 请检查消息格式和模型配置`, "Ngms API调用失败");
+ } else if (error.message.includes('401')) {
+ toastr.error(`API认证失败 (401): 请检查API Key配置`, "Ngms API调用失败");
+ } else if (error.message.includes('403')) {
+ toastr.error(`API访问被拒绝 (403): 请检查权限设置`, "Ngms API调用失败");
+ } else if (error.message.includes('429')) {
+ toastr.error(`API调用频率超限 (429): 请稍后重试`, "Ngms API调用失败");
+ } else if (error.message.includes('500')) {
+ toastr.error(`API服务器错误 (500): 请稍后重试`, "Ngms API调用失败");
+ } else {
+ toastr.error(`API调用失败: ${error.message}`, "Ngms API调用失败");
+ }
+
+ return null;
+ }
+}
+
+async function callNgmsOpenAITest(messages, options) {
+ const isGoogleApi = options.apiUrl.includes('googleapis.com');
+
+ const body = {
+ chat_completion_source: 'openai',
+ messages: messages,
+ model: options.model,
+ reverse_proxy: options.apiUrl,
+ proxy_password: options.apiKey,
+ stream: false,
+ max_tokens: options.maxTokens || 30000,
+ temperature: options.temperature || 1,
+ top_p: options.top_p || 1,
+ };
+
+ if (!isGoogleApi) {
+ Object.assign(body, {
+ custom_prompt_post_processing: 'strict',
+ enable_web_search: false,
+ frequency_penalty: 0,
+ group_names: [],
+ include_reasoning: false,
+ presence_penalty: 0.12,
+ reasoning_effort: 'medium',
+ request_images: false,
+ });
+ }
+
+ const response = await fetch('/api/backends/chat-completions/generate', {
+ method: 'POST',
+ headers: { ...getRequestHeaders(), 'Content-Type': 'application/json' },
+ body: JSON.stringify(body)
+ });
+
+ if (!response.ok) {
+ const errorText = await response.text();
+ throw new Error(`Ngms全兼容API请求失败: ${response.status} - ${errorText}`);
+ }
+
+ const responseData = await response.json();
+ return responseData?.choices?.[0]?.message?.content;
+}
+
+async function callNgmsSillyTavernPreset(messages, options) {
+ console.log('[Amily2号-NgmsST预设] 使用SillyTavern预设调用');
+
+ const context = getContext();
+ if (!context) {
+ throw new Error('无法获取SillyTavern上下文');
+ }
+
+ const profileId = options.tavernProfile;
+ if (!profileId) {
+ throw new Error('未配置SillyTavern预设ID');
+ }
+
+ let originalProfile = '';
+ let responsePromise;
+
+ try {
+ originalProfile = await amilyHelper.triggerSlash('/profile');
+ console.log(`[Amily2号-NgmsST预设] 当前配置文件: ${originalProfile}`);
+
+ const targetProfile = context.extensionSettings?.connectionManager?.profiles?.find(p => p.id === profileId);
+ if (!targetProfile) {
+ throw new Error(`未找到配置文件ID: ${profileId}`);
+ }
+
+ const targetProfileName = targetProfile.name;
+ console.log(`[Amily2号-NgmsST预设] 目标配置文件: ${targetProfileName}`);
+
+ const currentProfile = await amilyHelper.triggerSlash('/profile');
+ if (currentProfile !== targetProfileName) {
+ console.log(`[Amily2号-NgmsST预设] 切换配置文件: ${currentProfile} -> ${targetProfileName}`);
+ const escapedProfileName = targetProfileName.replace(/"/g, '\\"');
+ await amilyHelper.triggerSlash(`/profile await=true "${escapedProfileName}"`);
+ }
+
+ if (!context.ConnectionManagerRequestService) {
+ throw new Error('ConnectionManagerRequestService不可用');
+ }
+
+ console.log(`[Amily2号-NgmsST预设] 通过配置文件 ${targetProfileName} 发送请求`);
+ responsePromise = context.ConnectionManagerRequestService.sendRequest(
+ targetProfile.id,
+ messages,
+ options.maxTokens || 4000
+ );
+
+ } finally {
+ try {
+ const currentProfileAfterCall = await amilyHelper.triggerSlash('/profile');
+ if (originalProfile && originalProfile !== currentProfileAfterCall) {
+ console.log(`[Amily2号-NgmsST预设] 恢复原始配置文件: ${currentProfileAfterCall} -> ${originalProfile}`);
+ const escapedOriginalProfile = originalProfile.replace(/"/g, '\\"');
+ await amilyHelper.triggerSlash(`/profile await=true "${escapedOriginalProfile}"`);
+ }
+ } catch (restoreError) {
+ console.error('[Amily2号-NgmsST预设] 恢复配置文件失败:', restoreError);
+ }
+ }
+
+ const result = await responsePromise;
+
+ if (!result) {
+ throw new Error('未收到API响应');
+ }
+
+ const normalizedResult = normalizeApiResponse(result);
+ if (normalizedResult.error) {
+ throw new Error(normalizedResult.error.message || 'SillyTavern预设API调用失败');
+ }
+
+ return normalizedResult.content;
+}
+
+export async function fetchNgmsModels() {
+ console.log('[Amily2号-Ngms外交部] 开始获取模型列表');
+
+ const apiSettings = getNgmsApiSettings();
+
+ try {
+ if (apiSettings.apiMode === 'sillytavern_preset') {
+ // SillyTavern预设模式:获取当前预设的模型
+ const context = getContext();
+ if (!context?.extensionSettings?.connectionManager?.profiles) {
+ throw new Error('无法获取SillyTavern配置文件列表');
+ }
+
+ const targetProfile = context.extensionSettings.connectionManager.profiles.find(p => p.id === apiSettings.tavernProfile);
+ if (!targetProfile) {
+ throw new Error(`未找到配置文件ID: ${apiSettings.tavernProfile}`);
+ }
+
+ const models = [];
+ if (targetProfile.openai_model) {
+ models.push({ id: targetProfile.openai_model, name: targetProfile.openai_model });
+ }
+
+ if (models.length === 0) {
+ throw new Error('当前预设未配置模型');
+ }
+
+ console.log('[Amily2号-Ngms外交部] SillyTavern预设模式获取到模型:', models);
+ return models;
+
+ } else {
+ if (!apiSettings.apiUrl || !apiSettings.apiKey) {
+ throw new Error('API URL或Key未配置');
+ }
+
+ const response = await fetch('/api/backends/chat-completions/status', {
+ method: 'POST',
+ headers: {
+ ...getRequestHeaders(),
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ reverse_proxy: apiSettings.apiUrl,
+ proxy_password: apiSettings.apiKey,
+ chat_completion_source: 'openai'
+ })
+ });
+
+ if (!response.ok) {
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
+ }
+
+ const rawData = await response.json();
+ const models = Array.isArray(rawData) ? rawData : (rawData.data || rawData.models || []);
+
+ if (!Array.isArray(models)) {
+ const errorMessage = result.error?.message || 'API未返回有效的模型列表数组';
+ throw new Error(errorMessage);
+ }
+
+ const formattedModels = models
+ .map(m => {
+ // 从name字段中提取模型名称,去掉"models/"前缀
+ const modelIdRaw = m.name || m.id || m.model || m;
+ const modelName = String(modelIdRaw).replace(/^models\//, '');
+ return {
+ id: modelName,
+ name: modelName
+ };
+ })
+ .filter(m => m.id)
+ .sort((a, b) => String(a.name).localeCompare(String(b.name)));
+
+ console.log('[Amily2号-Ngms外交部] 全兼容模式获取到模型:', formattedModels);
+ return formattedModels;
+ }
+ } catch (error) {
+ console.error('[Amily2号-Ngms外交部] 获取模型列表失败:', error);
+ toastr.error(`获取模型列表失败: ${error.message}`, 'Ngms API');
+ throw error;
+ }
+}
+
+export async function testNgmsApiConnection() {
+ console.log('[Amily2号-Ngms外交部] 开始API连接测试');
+
+ const apiSettings = getNgmsApiSettings();
+
+ if (apiSettings.apiMode === 'sillytavern_preset') {
+ if (!apiSettings.tavernProfile) {
+ toastr.error('未配置SillyTavern预设ID', 'Ngms API连接测试失败');
+ return false;
+ }
+ } else {
+ if (!apiSettings.apiUrl || !apiSettings.apiKey || !apiSettings.model) {
+ toastr.error('API配置不完整,请检查URL、Key和模型', 'Ngms API连接测试失败');
+ return false;
+ }
+ }
+
+ try {
+ toastr.info('正在发送测试消息"你好!"...', 'Ngms API连接测试');
+
+ const userName = window.SillyTavern.getContext?.()?.name1 || '用户';
+ const systemPrompt = `接下来用户会使用测试按钮测试api连接是否正常,请回复ta连接是正常的,称呼用户为:“${userName}大人”,并复述群号1060183271,告知ta,本扩展开发者:“诗与酒.”正静待ta的入驻。`;
+
+ const testMessages = [
+ { role: 'system', content: systemPrompt },
+ { role: 'user', content: '你好!' }
+ ];
+
+ const response = await callNgmsAI(testMessages);
+
+ if (response && response.trim()) {
+ console.log('[Amily2号-Ngms外交部] 测试消息响应:', response);
+ const formattedResponse = response.replace(/\*\*(.*?)\*\*/g, '
$1');
+ toastr.success(`连接测试成功!AI回复: "${formattedResponse}"`, 'Ngms API连接测试成功', { "escapeHtml": false });
+ return true;
+ } else {
+ throw new Error('API未返回有效响应');
+ }
+
+ } catch (error) {
+ console.error('[Amily2号-Ngms外交部] 连接测试失败:', error);
+ toastr.error(`连接测试失败: ${error.message}`, 'Ngms API连接测试失败');
+ return false;
+ }
+}
diff --git a/core/api/SybdApi.js b/core/api/SybdApi.js
index 9dc86f6..542b9d3 100644
--- a/core/api/SybdApi.js
+++ b/core/api/SybdApi.js
@@ -1,388 +1,385 @@
-import { extension_settings, getContext } from "/scripts/extensions.js";
-import { characters, this_chid, getRequestHeaders, saveSettingsDebounced, eventSource, event_types } from "/script.js";
-import { extensionName } from "../../utils/settings.js";
-
-let ChatCompletionService = undefined;
-try {
- const module = await import('/scripts/custom-request.js');
- ChatCompletionService = module.ChatCompletionService;
- console.log('[Amily2号-Sybd外交部] 已成功召唤"皇家信使"(ChatCompletionService)。');
-} catch (e) {
- console.warn("[Amily2号-Sybd外交部] 未能召唤“皇家信使”,部分高级功能(如Claw代理)将受限。请考虑更新SillyTavern版本。", e);
-}
-
-function normalizeApiResponse(responseData) {
- let data = responseData;
- if (typeof data === 'string') {
- try {
- data = JSON.parse(data);
- } catch (e) {
- console.error(`[${extensionName}] Sybd API响应JSON解析失败:`, e);
- return { error: { message: 'Invalid JSON response' } };
- }
- }
- if (data && typeof data.data === 'object' && data.data !== null && !Array.isArray(data.data)) {
- if (Object.hasOwn(data.data, 'data')) {
- data = data.data;
- }
- }
- if (data && data.choices && data.choices[0]) {
- return { content: data.choices[0].message?.content?.trim() };
- }
- if (data && data.content) {
- return { content: data.content.trim() };
- }
- if (data && data.data) {
- return { data: data.data };
- }
- if (data && data.error) {
- return { error: data.error };
- }
- return data;
-}
-
-export function getSybdApiSettings() {
- return {
- apiMode: extension_settings[extensionName]?.sybdApiMode || 'openai_test',
- apiUrl: extension_settings[extensionName]?.sybdApiUrl?.trim() || '',
- apiKey: extension_settings[extensionName]?.sybdApiKey?.trim() || '',
- model: extension_settings[extensionName]?.sybdModel || '',
- maxTokens: extension_settings[extensionName]?.sybdMaxTokens || 4000,
- temperature: extension_settings[extensionName]?.sybdTemperature || 0.7,
- tavernProfile: extension_settings[extensionName]?.sybdTavernProfile || ''
- };
-}
-
-export async function callSybdAI(messages, options = {}) {
- if (window.AMILY2_SYSTEM_PARALYZED === true) {
- console.error("[Amily2-Sybd制裁] 系统完整性已受损,所有外交活动被无限期中止。");
- return null;
- }
-
- const apiSettings = getSybdApiSettings();
-
- const finalOptions = {
- maxTokens: apiSettings.maxTokens,
- temperature: apiSettings.temperature,
- model: apiSettings.model,
- apiUrl: apiSettings.apiUrl,
- apiKey: apiSettings.apiKey,
- apiMode: apiSettings.apiMode,
- tavernProfile: apiSettings.tavernProfile,
- ...options
- };
-
- if (finalOptions.apiMode !== 'sillytavern_preset') {
- if (!finalOptions.apiUrl || !finalOptions.model || !finalOptions.apiKey) {
- console.warn("[Amily2-Sybd外交部] API配置不完整,无法调用AI");
- toastr.error("API配置不完整,请检查URL、Key和模型配置。", "Sybd-外交部");
- return null;
- }
- }
-
- console.groupCollapsed(`[Amily2号-Sybd统一API调用] ${new Date().toLocaleTimeString()}`);
- console.log("【请求参数】:", {
- mode: finalOptions.apiMode,
- model: finalOptions.model,
- maxTokens: finalOptions.maxTokens,
- temperature: finalOptions.temperature,
- messagesCount: messages.length
- });
- console.log("【消息内容】:", messages);
- console.groupEnd();
-
- try {
- let responseContent;
-
- switch (finalOptions.apiMode) {
- case 'openai_test':
- responseContent = await callSybdOpenAITest(messages, finalOptions);
- break;
- case 'sillytavern_preset':
- responseContent = await callSybdSillyTavernPreset(messages, finalOptions);
- break;
- default:
- console.error(`[Amily2-Sybd外交部] 未支持的API模式: ${finalOptions.apiMode}`);
- return null;
- }
-
- if (!responseContent) {
- console.warn('[Amily2-Sybd外交部] 未能获取AI响应内容');
- return null;
- }
-
- console.groupCollapsed("[Amily2号-Sybd AI回复]");
- console.log(responseContent);
- console.groupEnd();
-
- return responseContent;
-
- } catch (error) {
- console.error(`[Amily2-Sybd外交部] API调用发生错误:`, error);
-
- if (error.message.includes('400')) {
- toastr.error(`API请求格式错误 (400): 请检查消息格式和模型配置`, "Sybd API调用失败");
- } else if (error.message.includes('401')) {
- toastr.error(`API认证失败 (401): 请检查API Key配置`, "Sybd API调用失败");
- } else if (error.message.includes('403')) {
- toastr.error(`API访问被拒绝 (403): 请检查权限设置`, "Sybd API调用失败");
- } else if (error.message.includes('429')) {
- toastr.error(`API调用频率超限 (429): 请稍后重试`, "Sybd API调用失败");
- } else if (error.message.includes('500')) {
- toastr.error(`API服务器错误 (500): 请稍后重试`, "Sybd API调用失败");
- } else {
- toastr.error(`API调用失败: ${error.message}`, "Sybd API调用失败");
- }
-
- return null;
- }
-}
-
-async function callSybdOpenAITest(messages, options) {
- const isGoogleApi = options.apiUrl.includes('googleapis.com');
-
- const body = {
- chat_completion_source: 'openai',
- messages: messages,
- model: options.model,
- reverse_proxy: options.apiUrl,
- proxy_password: options.apiKey,
- stream: false,
- max_tokens: options.maxTokens || 30000,
- temperature: options.temperature || 1,
- top_p: options.top_p || 1,
- };
-
- if (!isGoogleApi) {
- Object.assign(body, {
- custom_prompt_post_processing: 'strict',
- enable_web_search: false,
- frequency_penalty: 0,
- group_names: [],
- include_reasoning: false,
- presence_penalty: 0.12,
- reasoning_effort: 'medium',
- request_images: false,
- });
- }
-
- const response = await fetch('/api/backends/chat-completions/generate', {
- method: 'POST',
- headers: { ...getRequestHeaders(), 'Content-Type': 'application/json' },
- body: JSON.stringify(body)
- });
-
- if (!response.ok) {
- const errorText = await response.text();
- throw new Error(`Sybd全兼容API请求失败: ${response.status} - ${errorText}`);
- }
-
- const responseData = await response.json();
- return responseData?.choices?.[0]?.message?.content;
-}
-
-async function callSybdSillyTavernPreset(messages, options) {
- console.log('[Amily2号-SybdST预设] 使用SillyTavern预设调用');
-
- if (!window.TavernHelper || !window.TavernHelper.triggerSlash) {
- throw new Error('TavernHelper不可用,无法使用SillyTavern预设模式');
- }
-
- const context = getContext();
- if (!context) {
- throw new Error('无法获取SillyTavern上下文');
- }
-
- const profileId = options.tavernProfile;
- if (!profileId) {
- throw new Error('未配置SillyTavern预设ID');
- }
-
- let originalProfile = '';
- let responsePromise;
-
- try {
- originalProfile = await window.TavernHelper.triggerSlash('/profile');
- console.log(`[Amily2号-SybdST预设] 当前配置文件: ${originalProfile}`);
-
- const targetProfile = context.extensionSettings?.connectionManager?.profiles?.find(p => p.id === profileId);
- if (!targetProfile) {
- throw new Error(`未找到配置文件ID: ${profileId}`);
- }
-
- const targetProfileName = targetProfile.name;
- console.log(`[Amily2号-SybdST预设] 目标配置文件: ${targetProfileName}`);
-
- const currentProfile = await window.TavernHelper.triggerSlash('/profile');
- if (currentProfile !== targetProfileName) {
- console.log(`[Amily2号-SybdST预设] 切换配置文件: ${currentProfile} -> ${targetProfileName}`);
- const escapedProfileName = targetProfileName.replace(/"/g, '\\"');
- await window.TavernHelper.triggerSlash(`/profile await=true "${escapedProfileName}"`);
- }
-
- if (!context.ConnectionManagerRequestService) {
- throw new Error('ConnectionManagerRequestService不可用');
- }
-
- console.log(`[Amily2号-SybdST预设] 通过配置文件 ${targetProfileName} 发送请求`);
- responsePromise = context.ConnectionManagerRequestService.sendRequest(
- targetProfile.id,
- messages,
- options.maxTokens || 4000
- );
-
- } finally {
- try {
- const currentProfileAfterCall = await window.TavernHelper.triggerSlash('/profile');
- if (originalProfile && originalProfile !== currentProfileAfterCall) {
- console.log(`[Amily2号-SybdST预设] 恢复原始配置文件: ${currentProfileAfterCall} -> ${originalProfile}`);
- const escapedOriginalProfile = originalProfile.replace(/"/g, '\\"');
- await window.TavernHelper.triggerSlash(`/profile await=true "${escapedOriginalProfile}"`);
- }
- } catch (restoreError) {
- console.error('[Amily2号-SybdST预设] 恢复配置文件失败:', restoreError);
- }
- }
-
- const result = await responsePromise;
-
- if (!result) {
- throw new Error('未收到API响应');
- }
-
- const normalizedResult = normalizeApiResponse(result);
- if (normalizedResult.error) {
- throw new Error(normalizedResult.error.message || 'SillyTavern预设API调用失败');
- }
-
- return normalizedResult.content;
-}
-
-export async function fetchSybdModels() {
- console.log('[Amily2号-Sybd外交部] 开始获取模型列表');
-
- const apiSettings = getSybdApiSettings();
-
- try {
- if (apiSettings.apiMode === 'sillytavern_preset') {
- // SillyTavern预设模式:获取当前预设的模型
- const context = getContext();
- if (!context?.extensionSettings?.connectionManager?.profiles) {
- throw new Error('无法获取SillyTavern配置文件列表');
- }
-
- const targetProfile = context.extensionSettings.connectionManager.profiles.find(p => p.id === apiSettings.tavernProfile);
- if (!targetProfile) {
- throw new Error(`未找到配置文件ID: ${apiSettings.tavernProfile}`);
- }
-
- const models = [];
- if (targetProfile.openai_model) {
- models.push({ id: targetProfile.openai_model, name: targetProfile.openai_model });
- }
-
- if (models.length === 0) {
- throw new Error('当前预设未配置模型');
- }
-
- console.log('[Amily2号-Sybd外交部] SillyTavern预设模式获取到模型:', models);
- return models;
-
- } else {
- if (!apiSettings.apiUrl || !apiSettings.apiKey) {
- throw new Error('API URL或Key未配置');
- }
-
- const response = await fetch('/api/backends/chat-completions/status', {
- method: 'POST',
- headers: {
- ...getRequestHeaders(),
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- reverse_proxy: apiSettings.apiUrl,
- proxy_password: apiSettings.apiKey,
- chat_completion_source: 'openai'
- })
- });
-
- if (!response.ok) {
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
- }
-
- const rawData = await response.json();
- const models = Array.isArray(rawData) ? rawData : (rawData.data || rawData.models || []);
-
- if (!Array.isArray(models)) {
- const errorMessage = result.error?.message || 'API未返回有效的模型列表数组';
- throw new Error(errorMessage);
- }
-
- const formattedModels = models
- .map(m => {
- // 从name字段中提取模型名称,去掉"models/"前缀
- const modelIdRaw = m.name || m.id || m.model || m;
- const modelName = String(modelIdRaw).replace(/^models\//, '');
- return {
- id: modelName,
- name: modelName
- };
- })
- .filter(m => m.id)
- .sort((a, b) => String(a.name).localeCompare(String(b.name)));
-
- console.log('[Amily2号-Sybd外交部] 全兼容模式获取到模型:', formattedModels);
- return formattedModels;
- }
- } catch (error) {
- console.error('[Amily2号-Sybd外交部] 获取模型列表失败:', error);
- toastr.error(`获取模型列表失败: ${error.message}`, 'Sybd API');
- throw error;
- }
-}
-
-export async function testSybdApiConnection() {
- console.log('[Amily2号-Sybd外交部] 开始API连接测试');
-
- const apiSettings = getSybdApiSettings();
-
- if (apiSettings.apiMode === 'sillytavern_preset') {
- if (!apiSettings.tavernProfile) {
- toastr.error('未配置SillyTavern预设ID', 'Sybd API连接测试失败');
- return false;
- }
- } else {
- if (!apiSettings.apiUrl || !apiSettings.apiKey || !apiSettings.model) {
- toastr.error('API配置不完整,请检查URL、Key和模型', 'Sybd API连接测试失败');
- return false;
- }
- }
-
- try {
- toastr.info('正在发送测试消息"你好!"...', 'Sybd API连接测试');
-
- const userName = window.SillyTavern.getContext?.()?.name1 || '用户';
- const systemPrompt = `接下来用户会使用测试按钮测试api连接是否正常,请回复ta连接是正常的,称呼用户为:“${userName}大人”,并复述群号1060183271,告知ta,本扩展开发者:“诗与酒.”正静待ta的入驻。`;
-
- const testMessages = [
- { role: 'system', content: systemPrompt },
- { role: 'user', content: '你好!' }
- ];
-
- const response = await callSybdAI(testMessages);
-
- if (response && response.trim()) {
- console.log('[Amily2号-Sybd外交部] 测试消息响应:', response);
- const formattedResponse = response.replace(/\*\*(.*?)\*\*/g, '
$1');
- toastr.success(`连接测试成功!AI回复: "${formattedResponse}"`, 'Sybd API连接测试成功', { "escapeHtml": false });
- return true;
- } else {
- throw new Error('API未返回有效响应');
- }
-
- } catch (error) {
- console.error('[Amily2号-Sybd外交部] 连接测试失败:', error);
- toastr.error(`连接测试失败: ${error.message}`, 'Sybd API连接测试失败');
- return false;
- }
-}
+import { extension_settings, getContext } from "/scripts/extensions.js";
+import { characters, this_chid, getRequestHeaders, saveSettingsDebounced, eventSource, event_types } from "/script.js";
+import { extensionName } from "../../utils/settings.js";
+import { amilyHelper } from '../../core/tavern-helper/main.js';
+
+let ChatCompletionService = undefined;
+try {
+ const module = await import('/scripts/custom-request.js');
+ ChatCompletionService = module.ChatCompletionService;
+ console.log('[Amily2号-Sybd外交部] 已成功召唤"皇家信使"(ChatCompletionService)。');
+} catch (e) {
+ console.warn("[Amily2号-Sybd外交部] 未能召唤“皇家信使”,部分高级功能(如Claw代理)将受限。请考虑更新SillyTavern版本。", e);
+}
+
+function normalizeApiResponse(responseData) {
+ let data = responseData;
+ if (typeof data === 'string') {
+ try {
+ data = JSON.parse(data);
+ } catch (e) {
+ console.error(`[${extensionName}] Sybd API响应JSON解析失败:`, e);
+ return { error: { message: 'Invalid JSON response' } };
+ }
+ }
+ if (data && typeof data.data === 'object' && data.data !== null && !Array.isArray(data.data)) {
+ if (Object.hasOwn(data.data, 'data')) {
+ data = data.data;
+ }
+ }
+ if (data && data.choices && data.choices[0]) {
+ return { content: data.choices[0].message?.content?.trim() };
+ }
+ if (data && data.content) {
+ return { content: data.content.trim() };
+ }
+ if (data && data.data) {
+ return { data: data.data };
+ }
+ if (data && data.error) {
+ return { error: data.error };
+ }
+ return data;
+}
+
+export function getSybdApiSettings() {
+ return {
+ apiMode: extension_settings[extensionName]?.sybdApiMode || 'openai_test',
+ apiUrl: extension_settings[extensionName]?.sybdApiUrl?.trim() || '',
+ apiKey: extension_settings[extensionName]?.sybdApiKey?.trim() || '',
+ model: extension_settings[extensionName]?.sybdModel || '',
+ maxTokens: extension_settings[extensionName]?.sybdMaxTokens || 4000,
+ temperature: extension_settings[extensionName]?.sybdTemperature || 0.7,
+ tavernProfile: extension_settings[extensionName]?.sybdTavernProfile || ''
+ };
+}
+
+export async function callSybdAI(messages, options = {}) {
+ if (window.AMILY2_SYSTEM_PARALYZED === true) {
+ console.error("[Amily2-Sybd制裁] 系统完整性已受损,所有外交活动被无限期中止。");
+ return null;
+ }
+
+ const apiSettings = getSybdApiSettings();
+
+ const finalOptions = {
+ maxTokens: apiSettings.maxTokens,
+ temperature: apiSettings.temperature,
+ model: apiSettings.model,
+ apiUrl: apiSettings.apiUrl,
+ apiKey: apiSettings.apiKey,
+ apiMode: apiSettings.apiMode,
+ tavernProfile: apiSettings.tavernProfile,
+ ...options
+ };
+
+ if (finalOptions.apiMode !== 'sillytavern_preset') {
+ if (!finalOptions.apiUrl || !finalOptions.model || !finalOptions.apiKey) {
+ console.warn("[Amily2-Sybd外交部] API配置不完整,无法调用AI");
+ toastr.error("API配置不完整,请检查URL、Key和模型配置。", "Sybd-外交部");
+ return null;
+ }
+ }
+
+ console.groupCollapsed(`[Amily2号-Sybd统一API调用] ${new Date().toLocaleTimeString()}`);
+ console.log("【请求参数】:", {
+ mode: finalOptions.apiMode,
+ model: finalOptions.model,
+ maxTokens: finalOptions.maxTokens,
+ temperature: finalOptions.temperature,
+ messagesCount: messages.length
+ });
+ console.log("【消息内容】:", messages);
+ console.groupEnd();
+
+ try {
+ let responseContent;
+
+ switch (finalOptions.apiMode) {
+ case 'openai_test':
+ responseContent = await callSybdOpenAITest(messages, finalOptions);
+ break;
+ case 'sillytavern_preset':
+ responseContent = await callSybdSillyTavernPreset(messages, finalOptions);
+ break;
+ default:
+ console.error(`[Amily2-Sybd外交部] 未支持的API模式: ${finalOptions.apiMode}`);
+ return null;
+ }
+
+ if (!responseContent) {
+ console.warn('[Amily2-Sybd外交部] 未能获取AI响应内容');
+ return null;
+ }
+
+ console.groupCollapsed("[Amily2号-Sybd AI回复]");
+ console.log(responseContent);
+ console.groupEnd();
+
+ return responseContent;
+
+ } catch (error) {
+ console.error(`[Amily2-Sybd外交部] API调用发生错误:`, error);
+
+ if (error.message.includes('400')) {
+ toastr.error(`API请求格式错误 (400): 请检查消息格式和模型配置`, "Sybd API调用失败");
+ } else if (error.message.includes('401')) {
+ toastr.error(`API认证失败 (401): 请检查API Key配置`, "Sybd API调用失败");
+ } else if (error.message.includes('403')) {
+ toastr.error(`API访问被拒绝 (403): 请检查权限设置`, "Sybd API调用失败");
+ } else if (error.message.includes('429')) {
+ toastr.error(`API调用频率超限 (429): 请稍后重试`, "Sybd API调用失败");
+ } else if (error.message.includes('500')) {
+ toastr.error(`API服务器错误 (500): 请稍后重试`, "Sybd API调用失败");
+ } else {
+ toastr.error(`API调用失败: ${error.message}`, "Sybd API调用失败");
+ }
+
+ return null;
+ }
+}
+
+async function callSybdOpenAITest(messages, options) {
+ const isGoogleApi = options.apiUrl.includes('googleapis.com');
+
+ const body = {
+ chat_completion_source: 'openai',
+ messages: messages,
+ model: options.model,
+ reverse_proxy: options.apiUrl,
+ proxy_password: options.apiKey,
+ stream: false,
+ max_tokens: options.maxTokens || 30000,
+ temperature: options.temperature || 1,
+ top_p: options.top_p || 1,
+ };
+
+ if (!isGoogleApi) {
+ Object.assign(body, {
+ custom_prompt_post_processing: 'strict',
+ enable_web_search: false,
+ frequency_penalty: 0,
+ group_names: [],
+ include_reasoning: false,
+ presence_penalty: 0.12,
+ reasoning_effort: 'medium',
+ request_images: false,
+ });
+ }
+
+ const response = await fetch('/api/backends/chat-completions/generate', {
+ method: 'POST',
+ headers: { ...getRequestHeaders(), 'Content-Type': 'application/json' },
+ body: JSON.stringify(body)
+ });
+
+ if (!response.ok) {
+ const errorText = await response.text();
+ throw new Error(`Sybd全兼容API请求失败: ${response.status} - ${errorText}`);
+ }
+
+ const responseData = await response.json();
+ return responseData?.choices?.[0]?.message?.content;
+}
+
+async function callSybdSillyTavernPreset(messages, options) {
+ console.log('[Amily2号-SybdST预设] 使用SillyTavern预设调用');
+
+ const context = getContext();
+ if (!context) {
+ throw new Error('无法获取SillyTavern上下文');
+ }
+
+ const profileId = options.tavernProfile;
+ if (!profileId) {
+ throw new Error('未配置SillyTavern预设ID');
+ }
+
+ let originalProfile = '';
+ let responsePromise;
+
+ try {
+ originalProfile = await amilyHelper.triggerSlash('/profile');
+ console.log(`[Amily2号-SybdST预设] 当前配置文件: ${originalProfile}`);
+
+ const targetProfile = context.extensionSettings?.connectionManager?.profiles?.find(p => p.id === profileId);
+ if (!targetProfile) {
+ throw new Error(`未找到配置文件ID: ${profileId}`);
+ }
+
+ const targetProfileName = targetProfile.name;
+ console.log(`[Amily2号-SybdST预设] 目标配置文件: ${targetProfileName}`);
+
+ const currentProfile = await amilyHelper.triggerSlash('/profile');
+ if (currentProfile !== targetProfileName) {
+ console.log(`[Amily2号-SybdST预设] 切换配置文件: ${currentProfile} -> ${targetProfileName}`);
+ const escapedProfileName = targetProfileName.replace(/"/g, '\\"');
+ await amilyHelper.triggerSlash(`/profile await=true "${escapedProfileName}"`);
+ }
+
+ if (!context.ConnectionManagerRequestService) {
+ throw new Error('ConnectionManagerRequestService不可用');
+ }
+
+ console.log(`[Amily2号-SybdST预设] 通过配置文件 ${targetProfileName} 发送请求`);
+ responsePromise = context.ConnectionManagerRequestService.sendRequest(
+ targetProfile.id,
+ messages,
+ options.maxTokens || 4000
+ );
+
+ } finally {
+ try {
+ const currentProfileAfterCall = await amilyHelper.triggerSlash('/profile');
+ if (originalProfile && originalProfile !== currentProfileAfterCall) {
+ console.log(`[Amily2号-SybdST预设] 恢复原始配置文件: ${currentProfileAfterCall} -> ${originalProfile}`);
+ const escapedOriginalProfile = originalProfile.replace(/"/g, '\\"');
+ await amilyHelper.triggerSlash(`/profile await=true "${escapedOriginalProfile}"`);
+ }
+ } catch (restoreError) {
+ console.error('[Amily2号-SybdST预设] 恢复配置文件失败:', restoreError);
+ }
+ }
+
+ const result = await responsePromise;
+
+ if (!result) {
+ throw new Error('未收到API响应');
+ }
+
+ const normalizedResult = normalizeApiResponse(result);
+ if (normalizedResult.error) {
+ throw new Error(normalizedResult.error.message || 'SillyTavern预设API调用失败');
+ }
+
+ return normalizedResult.content;
+}
+
+export async function fetchSybdModels() {
+ console.log('[Amily2号-Sybd外交部] 开始获取模型列表');
+
+ const apiSettings = getSybdApiSettings();
+
+ try {
+ if (apiSettings.apiMode === 'sillytavern_preset') {
+ // SillyTavern预设模式:获取当前预设的模型
+ const context = getContext();
+ if (!context?.extensionSettings?.connectionManager?.profiles) {
+ throw new Error('无法获取SillyTavern配置文件列表');
+ }
+
+ const targetProfile = context.extensionSettings.connectionManager.profiles.find(p => p.id === apiSettings.tavernProfile);
+ if (!targetProfile) {
+ throw new Error(`未找到配置文件ID: ${apiSettings.tavernProfile}`);
+ }
+
+ const models = [];
+ if (targetProfile.openai_model) {
+ models.push({ id: targetProfile.openai_model, name: targetProfile.openai_model });
+ }
+
+ if (models.length === 0) {
+ throw new Error('当前预设未配置模型');
+ }
+
+ console.log('[Amily2号-Sybd外交部] SillyTavern预设模式获取到模型:', models);
+ return models;
+
+ } else {
+ if (!apiSettings.apiUrl || !apiSettings.apiKey) {
+ throw new Error('API URL或Key未配置');
+ }
+
+ const response = await fetch('/api/backends/chat-completions/status', {
+ method: 'POST',
+ headers: {
+ ...getRequestHeaders(),
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ reverse_proxy: apiSettings.apiUrl,
+ proxy_password: apiSettings.apiKey,
+ chat_completion_source: 'openai'
+ })
+ });
+
+ if (!response.ok) {
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
+ }
+
+ const rawData = await response.json();
+ const models = Array.isArray(rawData) ? rawData : (rawData.data || rawData.models || []);
+
+ if (!Array.isArray(models)) {
+ const errorMessage = result.error?.message || 'API未返回有效的模型列表数组';
+ throw new Error(errorMessage);
+ }
+
+ const formattedModels = models
+ .map(m => {
+ // 从name字段中提取模型名称,去掉"models/"前缀
+ const modelIdRaw = m.name || m.id || m.model || m;
+ const modelName = String(modelIdRaw).replace(/^models\//, '');
+ return {
+ id: modelName,
+ name: modelName
+ };
+ })
+ .filter(m => m.id)
+ .sort((a, b) => String(a.name).localeCompare(String(b.name)));
+
+ console.log('[Amily2号-Sybd外交部] 全兼容模式获取到模型:', formattedModels);
+ return formattedModels;
+ }
+ } catch (error) {
+ console.error('[Amily2号-Sybd外交部] 获取模型列表失败:', error);
+ toastr.error(`获取模型列表失败: ${error.message}`, 'Sybd API');
+ throw error;
+ }
+}
+
+export async function testSybdApiConnection() {
+ console.log('[Amily2号-Sybd外交部] 开始API连接测试');
+
+ const apiSettings = getSybdApiSettings();
+
+ if (apiSettings.apiMode === 'sillytavern_preset') {
+ if (!apiSettings.tavernProfile) {
+ toastr.error('未配置SillyTavern预设ID', 'Sybd API连接测试失败');
+ return false;
+ }
+ } else {
+ if (!apiSettings.apiUrl || !apiSettings.apiKey || !apiSettings.model) {
+ toastr.error('API配置不完整,请检查URL、Key和模型', 'Sybd API连接测试失败');
+ return false;
+ }
+ }
+
+ try {
+ toastr.info('正在发送测试消息"你好!"...', 'Sybd API连接测试');
+
+ const userName = window.SillyTavern.getContext?.()?.name1 || '用户';
+ const systemPrompt = `接下来用户会使用测试按钮测试api连接是否正常,请回复ta连接是正常的,称呼用户为:“${userName}大人”,并复述群号1060183271,告知ta,本扩展开发者:“诗与酒.”正静待ta的入驻。`;
+
+ const testMessages = [
+ { role: 'system', content: systemPrompt },
+ { role: 'user', content: '你好!' }
+ ];
+
+ const response = await callSybdAI(testMessages);
+
+ if (response && response.trim()) {
+ console.log('[Amily2号-Sybd外交部] 测试消息响应:', response);
+ const formattedResponse = response.replace(/\*\*(.*?)\*\*/g, '
$1');
+ toastr.success(`连接测试成功!AI回复: "${formattedResponse}"`, 'Sybd API连接测试成功', { "escapeHtml": false });
+ return true;
+ } else {
+ throw new Error('API未返回有效响应');
+ }
+
+ } catch (error) {
+ console.error('[Amily2号-Sybd外交部] 连接测试失败:', error);
+ toastr.error(`连接测试失败: ${error.message}`, 'Sybd API连接测试失败');
+ return false;
+ }
+}
diff --git a/core/commands.js b/core/commands.js
index 73b77ef..3f01098 100644
--- a/core/commands.js
+++ b/core/commands.js
@@ -1 +1,221 @@
-(function(_0x18689,_0x75b104){const _0x22eef5=_0x1e93,_0x211589=_0x18689();while(!![]){try{const _0x1fc4aa=parseInt(_0x22eef5(0x87))/0x1+-parseInt(_0x22eef5(0x9a))/0x2+parseInt(_0x22eef5(0xad))/0x3+parseInt(_0x22eef5(0x92))/0x4*(parseInt(_0x22eef5(0x95))/0x5)+-parseInt(_0x22eef5(0xa8))/0x6+parseInt(_0x22eef5(0xb3))/0x7*(-parseInt(_0x22eef5(0x8c))/0x8)+parseInt(_0x22eef5(0x9f))/0x9;if(_0x1fc4aa===_0x75b104)break;else _0x211589['push'](_0x211589['shift']());}catch(_0x155ea3){_0x211589['push'](_0x211589['shift']());}}}(_0x5a0e,0xd1ebd));import{getContext,extension_settings}from'/scripts/extensions.js';import{saveChatConditional,reloadCurrentChat}from'/script.js';import{extensionName}from'../utils/settings.js';import{SlashCommand}from'/scripts/slash-commands/SlashCommand.js';function _0x5a0e(){const _0x4d9310=['error','info','apiUrl','检测到问题,建议使用修复功能','需要至少2条消息才能测试','63libeyI','正在使用API检查回复...','正在使用API测试检测功能...','修复最新的AI回复中的问题','[Amily2]\x20致命错误:SlashCommand\x20或\x20SlashCommandParser\x20模块未能加载。','未检测到问题','mes','[Amily2-命令检查器]\x20已获取上下文消息:','正在检查并修复回复...','fix-reply','请先配置API\x20URL','测试结果:API未检测到问题,请检查API配置或提示词','592774fVyiKg','optimizedContent','...','最新消息是用户消息,无需检查','previousMessages','1233928GYQwMk','检查最新的AI回复是否有问题','[Amily2-新诏]\x20/fix-reply\x20命令已成功颁布。','[Amily2-命令检查器]\x20目标为用户消息,跳过。','contextMessages','[Amily2-命令检查器]\x20没有聊天记录。','180GJJBhk','[Amily2]\x20命令注册过程中发生意外错误:','message','184430ijBqSz','fromProps','命令检查器','addCommandObject','length','3144032mSqFRc','log','warning','未检测到需要修复的问题','check-reply','19929132pvOOTj','test-reply-checker','slice','success','chat','is_user','undefined','[Amily2-新诏]\x20/test-reply-checker\x20命令已成功颁布。','[Amily2-新诏]\x20/check-reply\x20命令已成功颁布。','5894136ufrcWW','没有找到可用于测试的AI消息','max','没有可修复的消息','测试聊天回复检查器功能','1006158NMrHEv'];_0x5a0e=function(){return _0x4d9310;};return _0x5a0e();}function _0x1e93(_0x594217,_0x4e8ad1){const _0x5a0e36=_0x5a0e();return _0x1e93=function(_0x1e9306,_0x1385fb){_0x1e9306=_0x1e9306-0x84;let _0x11a0cb=_0x5a0e36[_0x1e9306];return _0x11a0cb;},_0x1e93(_0x594217,_0x4e8ad1);}import{SlashCommandParser}from'/scripts/slash-commands/SlashCommandParser.js';import{checkAndFixWithAPI}from'./api.js';async function checkLatestMessage(){const _0x5426a2=_0x1e93,_0xd34af3=getContext(),_0x134d56=_0xd34af3[_0x5426a2(0xa3)]||[];if(!_0x134d56||_0x134d56['length']===0x0)return console[_0x5426a2(0x9b)](_0x5426a2(0x91)),{'message':null,'previousMessages':[]};const _0x6f9c91=_0x134d56[_0x134d56[_0x5426a2(0x99)]-0x1];console[_0x5426a2(0x9b)]('[Amily2-命令检查器]\x20正在侦测消息:',{'isUser':_0x6f9c91['is_user'],'messagePreview':_0x6f9c91['mes']?.['substring'](0x0,0x32)+_0x5426a2(0x89)});if(_0x6f9c91[_0x5426a2(0xa4)])return console[_0x5426a2(0x9b)](_0x5426a2(0x8f)),{'message':_0x6f9c91,'previousMessages':[]};const _0x2a6209=extension_settings[extensionName],_0xe8211a=_0x2a6209[_0x5426a2(0x90)]||0x2,_0x581bd8=Math[_0x5426a2(0xaa)](0x0,_0x134d56[_0x5426a2(0x99)]-_0xe8211a-0x1),_0x45c0ea=_0x134d56[_0x5426a2(0xa1)](_0x581bd8,_0x134d56[_0x5426a2(0x99)]-0x1);return console[_0x5426a2(0x9b)](_0x5426a2(0xba),{'count':_0x45c0ea[_0x5426a2(0x99)]}),{'message':_0x6f9c91,'previousMessages':_0x45c0ea};}async function checkCommand(){const _0xb1f058=_0x1e93,_0x391057=extension_settings[extensionName];if(!_0x391057['apiUrl'])return toastr[_0xb1f058(0xae)](_0xb1f058(0x85),'命令检查器'),'';const _0x52f2a0=await checkLatestMessage();if(!_0x52f2a0[_0xb1f058(0x94)]||_0x52f2a0[_0xb1f058(0x94)][_0xb1f058(0xa4)])return toastr[_0xb1f058(0xaf)](_0xb1f058(0x8a),_0xb1f058(0x97)),'';toastr['info'](_0xb1f058(0xb4),'命令检查器');const _0x50e800=await checkAndFixWithAPI(_0x52f2a0[_0xb1f058(0x94)],_0x52f2a0[_0xb1f058(0x8b)]);return _0x50e800&&_0x50e800[_0xb1f058(0x88)]&&_0x50e800[_0xb1f058(0x88)]!==_0x52f2a0['message'][_0xb1f058(0xb9)]?toastr[_0xb1f058(0x9c)](_0xb1f058(0xb1),_0xb1f058(0x97)):toastr[_0xb1f058(0xa2)](_0xb1f058(0xb8),_0xb1f058(0x97)),'';}export async function fixCommand(){const _0x34f052=_0x1e93,_0x2e8506=extension_settings[extensionName];if(!_0x2e8506[_0x34f052(0xb0)])return toastr[_0x34f052(0xae)](_0x34f052(0x85),_0x34f052(0x97)),'';const _0x419437=getContext(),_0x21071a=_0x419437[_0x34f052(0xa3)];if(!_0x21071a||_0x21071a[_0x34f052(0x99)]===0x0)return toastr[_0x34f052(0xaf)](_0x34f052(0xab),'命令检查器'),'';const _0x31d855=_0x21071a[_0x21071a['length']-0x1];if(_0x31d855[_0x34f052(0xa4)])return toastr[_0x34f052(0xaf)]('最新消息是用户消息,无需修复','命令检查器'),'';const _0x56bf1c=_0x2e8506['contextMessages']||0x2,_0x739a3a=Math[_0x34f052(0xaa)](0x0,_0x21071a[_0x34f052(0x99)]-0x1-_0x56bf1c),_0x5b8caa=_0x21071a[_0x34f052(0xa1)](_0x739a3a,_0x21071a[_0x34f052(0x99)]-0x1);toastr[_0x34f052(0xaf)](_0x34f052(0xbb),_0x34f052(0x97));const _0x2575e8=await checkAndFixWithAPI(_0x31d855,_0x5b8caa);return _0x2575e8&&_0x2575e8[_0x34f052(0x88)]&&_0x2575e8[_0x34f052(0x88)]!==_0x31d855[_0x34f052(0xb9)]?(_0x31d855[_0x34f052(0xb9)]=_0x2575e8[_0x34f052(0x88)],await saveChatConditional(),await reloadCurrentChat(),toastr[_0x34f052(0xa2)]('回复已修复',_0x34f052(0x97))):toastr[_0x34f052(0xaf)](_0x34f052(0x9d),'命令检查器'),'';}export async function testReplyChecker(){const _0x337447=_0x1e93,_0x4e0dc1=extension_settings[extensionName];if(!_0x4e0dc1[_0x337447(0xb0)])return toastr[_0x337447(0xae)]('请先配置API\x20URL',_0x337447(0x97)),'';const _0x55f607=getContext(),_0x83fffd=_0x55f607['chat'];if(!_0x83fffd||_0x83fffd[_0x337447(0x99)]<0x2)return toastr[_0x337447(0x9c)](_0x337447(0xb2),_0x337447(0x97)),'';let _0x53f0e1=null;for(let _0x129cbc=_0x83fffd[_0x337447(0x99)]-0x2;_0x129cbc>=0x0;_0x129cbc--){if(!_0x83fffd[_0x129cbc][_0x337447(0xa4)]){_0x53f0e1=_0x83fffd[_0x129cbc][_0x337447(0xb9)];break;}}if(!_0x53f0e1)return toastr['warning'](_0x337447(0xa9),_0x337447(0x97)),'';const _0x5c5890=_0x83fffd[_0x83fffd[_0x337447(0x99)]-0x1];if(_0x5c5890[_0x337447(0xa4)])return toastr[_0x337447(0x9c)]('最后一条消息是用户消息,无法测试',_0x337447(0x97)),'';const _0x492d95=_0x5c5890[_0x337447(0xb9)];_0x5c5890[_0x337447(0xb9)]=_0x53f0e1+'\x0a\x0a'+_0x53f0e1,toastr['info'](_0x337447(0xb5),'命令检查器');const _0x355121=_0x4e0dc1[_0x337447(0x90)]||0x2,_0x47f2a8=Math['max'](0x0,_0x83fffd[_0x337447(0x99)]-_0x355121-0x1),_0x57c82b=_0x83fffd[_0x337447(0xa1)](_0x47f2a8,_0x83fffd[_0x337447(0x99)]-0x1),_0x37e83d=await checkAndFixWithAPI(_0x5c5890,_0x57c82b);return _0x5c5890[_0x337447(0xb9)]=_0x492d95,_0x37e83d&&_0x37e83d[_0x337447(0x88)]&&_0x37e83d['optimizedContent']!==_0x53f0e1+'\x0a\x0a'+_0x53f0e1?toastr[_0x337447(0xa2)]('测试成功!API检测到重复内容并提供了修复建议','命令检查器'):toastr['warning'](_0x337447(0x86),_0x337447(0x97)),'';}export async function registerSlashCommands(){const _0x52e940=_0x1e93;try{if(typeof SlashCommand==='undefined'||typeof SlashCommandParser===_0x52e940(0xa5)){console[_0x52e940(0xae)](_0x52e940(0xb7));return;}SlashCommandParser[_0x52e940(0x98)](SlashCommand[_0x52e940(0x96)]({'name':_0x52e940(0x9e),'callback':checkCommand,'helpString':_0x52e940(0x8d)})),console['log'](_0x52e940(0xa7)),SlashCommandParser[_0x52e940(0x98)](SlashCommand[_0x52e940(0x96)]({'name':_0x52e940(0x84),'callback':fixCommand,'helpString':_0x52e940(0xb6)})),console[_0x52e940(0x9b)](_0x52e940(0x8e)),SlashCommandParser[_0x52e940(0x98)](SlashCommand[_0x52e940(0x96)]({'name':_0x52e940(0xa0),'callback':testReplyChecker,'helpString':_0x52e940(0xac)})),console[_0x52e940(0x9b)](_0x52e940(0xa6));}catch(_0x212a74){console[_0x52e940(0xae)](_0x52e940(0x93),_0x212a74);}}
\ No newline at end of file
+import { getContext, extension_settings } from "/scripts/extensions.js";
+import { saveChatConditional, reloadCurrentChat } from "/script.js";
+import { extensionName } from "../utils/settings.js";
+import { SlashCommand } from "/scripts/slash-commands/SlashCommand.js";
+import { SlashCommandParser } from "/scripts/slash-commands/SlashCommandParser.js";
+import { checkAndFixWithAPI } from "./api.js";
+
+async function checkLatestMessage() {
+ const context = getContext();
+ const chat = context.chat || [];
+
+ if (!chat || chat.length === 0) {
+ console.log("[Amily2-命令检查器] 没有聊天记录。");
+ return { message: null, previousMessages: [] };
+ }
+
+ const latestMessage = chat[chat.length - 1];
+
+ console.log("[Amily2-命令检查器] 正在侦测消息:", {
+ isUser: latestMessage.is_user,
+ messagePreview: latestMessage.mes?.substring(0, 50) + "...",
+ });
+
+ if (latestMessage.is_user) {
+ console.log("[Amily2-命令检查器] 目标为用户消息,跳过。");
+ return { message: latestMessage, previousMessages: [] };
+ }
+
+ const settings = extension_settings[extensionName];
+ const contextCount = settings.contextMessages || 2;
+ const startIndex = Math.max(0, chat.length - contextCount - 1);
+ const previousMessages = chat.slice(startIndex, chat.length - 1);
+
+ console.log("[Amily2-命令检查器] 已获取上下文消息:", {
+ count: previousMessages.length,
+ });
+
+ return { message: latestMessage, previousMessages };
+}
+
+async function checkCommand() {
+ const settings = extension_settings[extensionName];
+ if (!settings.apiUrl) {
+ toastr.error("请先配置API URL", "命令检查器");
+ return "";
+ }
+ const checkResult = await checkLatestMessage();
+ if (!checkResult.message || checkResult.message.is_user) {
+ toastr.info("最新消息是用户消息,无需检查", "命令检查器");
+ return "";
+ }
+ toastr.info("正在使用API检查回复...", "命令检查器");
+ const result = await checkAndFixWithAPI(
+ checkResult.message,
+ checkResult.previousMessages,
+ );
+ if (
+ result &&
+ result.optimizedContent &&
+ result.optimizedContent !== checkResult.message.mes
+ ) {
+ toastr.warning("检测到问题,建议使用修复功能", "命令检查器");
+ } else {
+ toastr.success("未检测到问题", "命令检查器");
+ }
+ return "";
+}
+
+
+export async function fixCommand() {
+ const settings = extension_settings[extensionName];
+ if (!settings.apiUrl) {
+ toastr.error("请先配置API URL", "命令检查器");
+ return "";
+ }
+ const context = getContext();
+ const chat = context.chat;
+ if (!chat || chat.length === 0) {
+ toastr.info("没有可修复的消息", "命令检查器");
+ return "";
+ }
+ const latestMessage = chat[chat.length - 1];
+ if (latestMessage.is_user) {
+ toastr.info("最新消息是用户消息,无需修复", "命令检查器");
+ return "";
+ }
+ const contextCount = settings.contextMessages || 2;
+ const startIndex = Math.max(0, chat.length - 1 - contextCount);
+ const previousMessages = chat.slice(startIndex, chat.length - 1);
+ toastr.info("正在检查并修复回复...", "命令检查器");
+ const result = await checkAndFixWithAPI(latestMessage, previousMessages);
+ if (
+ result &&
+ result.optimizedContent &&
+ result.optimizedContent !== latestMessage.mes
+ ) {
+ latestMessage.mes = result.optimizedContent;
+ await saveChatConditional();
+ await reloadCurrentChat();
+ toastr.success("回复已修复", "命令检查器");
+ } else {
+ toastr.info("未检测到需要修复的问题", "命令检查器");
+ }
+ return "";
+}
+
+export async function testReplyChecker() {
+ const settings = extension_settings[extensionName];
+ if (!settings.apiUrl) {
+ toastr.error("请先配置API URL", "命令检查器");
+ return "";
+ }
+ const context = getContext();
+ const chat = context.chat;
+ if (!chat || chat.length < 2) {
+ toastr.warning("需要至少2条消息才能测试", "命令检查器");
+ return "";
+ }
+ let testMessage = null;
+ for (let i = chat.length - 2; i >= 0; i--) {
+ if (!chat[i].is_user) {
+ testMessage = chat[i].mes;
+ break;
+ }
+ }
+ if (!testMessage) {
+ toastr.warning("没有找到可用于测试的AI消息", "命令检查器");
+ return "";
+ }
+ const lastMessage = chat[chat.length - 1];
+ if (lastMessage.is_user) {
+ toastr.warning("最后一条消息是用户消息,无法测试", "命令检查器");
+ return "";
+ }
+ const originalMessage = lastMessage.mes;
+ lastMessage.mes = testMessage + "\n\n" + testMessage;
+ toastr.info("正在使用API测试检测功能...", "命令检查器");
+ const contextCount = settings.contextMessages || 2;
+ const startIndex = Math.max(0, chat.length - contextCount - 1);
+ const previousMessages = chat.slice(startIndex, chat.length - 1);
+ const result = await checkAndFixWithAPI(lastMessage, previousMessages);
+ lastMessage.mes = originalMessage;
+ if (
+ result &&
+ result.optimizedContent &&
+ result.optimizedContent !== testMessage + "\n\n" + testMessage
+ ) {
+ toastr.success("测试成功!API检测到重复内容并提供了修复建议", "命令检查器");
+ } else {
+ toastr.warning(
+ "测试结果:API未检测到问题,请检查API配置或提示词",
+ "命令检查器",
+ );
+ }
+ return "";
+}
+
+async function triggerSendButton() {
+ // 模拟点击发送按钮
+ const sendButton = document.getElementById('send_but');
+ if (sendButton) {
+ sendButton.click();
+ console.log("[Amily2-触发器] 已触发发送按钮");
+ return "";
+ } else {
+ console.warn("[Amily2-触发器] 未找到发送按钮");
+ toastr.warning("未找到发送按钮", "触发器");
+ return "";
+ }
+}
+
+export async function registerSlashCommands() {
+ try {
+ if (
+ typeof SlashCommand === "undefined" ||
+ typeof SlashCommandParser === "undefined"
+ ) {
+ console.error(
+ "[Amily2] 致命错误:SlashCommand 或 SlashCommandParser 模块未能加载。",
+ );
+ return;
+ }
+ SlashCommandParser.addCommandObject(
+ SlashCommand.fromProps({
+ name: "check-reply",
+ callback: checkCommand,
+ helpString: "检查最新的AI回复是否有问题",
+ }),
+ );
+ console.log("[Amily2-新诏] /check-reply 命令已成功颁布。");
+
+ SlashCommandParser.addCommandObject(
+ SlashCommand.fromProps({
+ name: "fix-reply",
+ callback: fixCommand,
+ helpString: "修复最新的AI回复中的问题",
+ }),
+ );
+ console.log("[Amily2-新诏] /fix-reply 命令已成功颁布。");
+
+ SlashCommandParser.addCommandObject(
+ SlashCommand.fromProps({
+ name: "test-reply-checker",
+ callback: testReplyChecker,
+ helpString: "测试聊天回复检查器功能",
+ }),
+ );
+ console.log("[Amily2-新诏] /test-reply-checker 命令已成功颁布。");
+
+ SlashCommandParser.addCommandObject(
+ SlashCommand.fromProps({
+ name: "trigger",
+ callback: triggerSendButton,
+ helpString: "触发发送按钮 (用于自动发送消息)",
+ }),
+ );
+ console.log("[Amily2-新诏] /trigger 命令已成功颁布。");
+ } catch (e) {
+ console.error("[Amily2] 命令注册过程中发生意外错误:", e);
+ }
+}
diff --git a/core/historiographer.js b/core/historiographer.js
index a55c381..105c7b6 100644
--- a/core/historiographer.js
+++ b/core/historiographer.js
@@ -195,11 +195,8 @@ export async function executeManualSummary(startFloor, endFloor, isAuto = false)
container.find('.historiography-message-item').each(function() {
const item = $(this);
const authorType = item.data('author-type');
- if ((authorType === 'user' && !includeUser) || (authorType === 'char' && !includeChar)) {
- item.prop('hidden', true);
- } else {
- item.prop('hidden', false);
- }
+ const shouldBeHidden = (authorType === 'user' && !includeUser) || (authorType === 'char' && !includeChar);
+ item.toggle(!shouldBeHidden);
});
};
@@ -207,7 +204,17 @@ export async function executeManualSummary(startFloor, endFloor, isAuto = false)
charCheckbox.on('change', updateVisibility);
},
onOk: async (dialog) => {
- const textToSummarize = dialog.find('.historiography-message-item:not([hidden]) textarea')
+ const includeUser = dialog.find('#hist-include-user').is(':checked');
+ const includeChar = dialog.find('#hist-include-char').is(':checked');
+
+ const textToSummarize = dialog.find('.historiography-message-item')
+ .filter(function() {
+ const authorType = $(this).data('author-type');
+ if (authorType === 'user' && !includeUser) return false;
+ if (authorType === 'char' && !includeChar) return false;
+ return true;
+ })
+ .find('textarea')
.map(function() {
const floor = $(this).data('floor');
const author = $(this).closest('.historiography-message-item').find('summary').text().replace(`【第 ${floor} 楼】 `, '');
diff --git a/core/lore.js b/core/lore.js
index 98c458e..acd0ec8 100644
--- a/core/lore.js
+++ b/core/lore.js
@@ -1,10 +1,18 @@
import { extension_settings, getContext } from "/scripts/extensions.js";
import { characters, eventSource, event_types } from "/script.js";
-import { loadWorldInfo, createNewWorldInfo, createWorldInfoEntry, saveWorldInfo, world_names } from "/scripts/world-info.js";
+import { loadWorldInfo, createNewWorldInfo, createWorldInfoEntry, saveWorldInfo, world_names, updateWorldInfoList } from "/scripts/world-info.js";
import { compatibleWriteToLorebook, safeLorebooks, safeCharLorebooks, safeLorebookEntries } from "./tavernhelper-compatibility.js";
import { extensionName } from "../utils/settings.js";
+document.addEventListener('amily-lorebook-created', (event) => {
+ if (event.detail && event.detail.bookName) {
+ console.log(`[Amily2-国史馆] 监听到史书《${event.detail.bookName}》变更,即刻通报工部刷新宫殿。`);
+ refreshWorldbookListOnly(event.detail.bookName);
+ }
+});
+
+
export const LOREBOOK_PREFIX = "Amily2档案-";
export const DEDICATED_LOREBOOK_NAME = "Amily2号-国史馆";
export const INTRODUCTORY_TEXT =
@@ -90,34 +98,15 @@ export async function getCombinedWorldbookContent(lorebookName) {
}
}
-async function refreshWorldbookListOnly(newBookName = null) {
- console.log("[Amily2号-工部-v1.3] 执行“圣谕广播”式UI更新...");
- try {
- if (newBookName) {
- if (Array.isArray(world_names) && !world_names.includes(newBookName)) {
- world_names.push(newBookName);
- world_names.sort();
- console.log(`[Amily2号-工部] 已将《${newBookName}》注入前端数据模型。`);
- } else {
- console.log(`[Amily2号-工部] 《${newBookName}》已存在于数据模型中,跳过注入。`);
- }
+export async function refreshWorldbookListOnly(newBookName = null) {
+ console.log("[Amily2号-工部-v2.0] 执行SillyTavern核心UI刷新...");
+ try {
+ await updateWorldInfoList();
+ console.log("[Amily2号-工部] SillyTavern核心刷新函数 (updateWorldInfoList) 调用成功。");
+ } catch (error) {
+ console.error("[Amily2号-工部] 调用核心刷新函数时出错:", error);
+ toastr.error("Amily2号调用核心UI刷新函数时失败。", "核心刷新失败");
}
-
- if (
- eventSource &&
- typeof eventSource.emit === "function" &&
- event_types.CHARACTER_PAGE_LOADED
- ) {
- console.log(`[Amily2号-工部] 正在广播事件: ${event_types.CHARACTER_PAGE_LOADED}`);
- eventSource.emit(event_types.CHARACTER_PAGE_LOADED);
- console.log("[Amily2号-工部] “character_page_loaded”事件已广播,UI应已响应刷新。");
- } else {
- console.error("[Amily2号] 致命错误: eventSource 或 event_types.CHARACTER_PAGE_LOADED 未找到。无法广播刷新事件。");
- toastr.error("Amily2号无法触发UI刷新。", "核心事件系统缺失");
- }
- } catch (error) {
- console.error("[Amily2号-工部] “圣谕广播”式刷新失败:", error);
- }
}
export async function writeSummaryToLorebook(pendingData) {
@@ -281,7 +270,12 @@ export async function getPlotOptimizedWorldbookContent(context, apiSettings) {
const panel = $('#amily2_plot_optimization_panel');
let liveSettings = {};
- if (panel.length > 0) {
+ // Check if the panel exists and its dynamic content (the entry list) has been populated.
+ // This helps prevent a race condition where we read from an empty, partially-rendered panel.
+ const isPanelReady = panel.length > 0 && panel.find('#amily2_opt_worldbook_entry_list_container input[type="checkbox"]').length > 0;
+
+ if (isPanelReady) {
+ // Panel is ready, so we can trust the live values from the UI.
liveSettings.worldbookEnabled = panel.find('#amily2_opt_worldbook_enabled').is(':checked');
liveSettings.worldbookSource = panel.find('input[name="amily2_opt_worldbook_source"]:checked').val() || 'character';
@@ -295,25 +289,30 @@ export async function getPlotOptimizedWorldbookContent(context, apiSettings) {
liveSettings.worldbookCharLimit = parseInt(panel.find('#amily2_opt_worldbook_char_limit').val(), 10) || 60000;
let enabledEntries = {};
- panel.find('#amily2_opt_worldbook_entry_list_container input[type="checkbox"]').each(function() {
- if ($(this).is(':checked')) {
- const bookName = $(this).data('book');
- const uid = parseInt($(this).data('uid'));
- if (!enabledEntries[bookName]) {
- enabledEntries[bookName] = [];
- }
- enabledEntries[bookName].push(uid);
+ panel.find('#amily2_opt_worldbook_entry_list_container input[type="checkbox"]:checked').each(function() {
+ const bookName = $(this).data('book');
+ const uid = parseInt($(this).data('uid'));
+ if (!enabledEntries[bookName]) {
+ enabledEntries[bookName] = [];
}
+ enabledEntries[bookName].push(uid);
});
liveSettings.enabledWorldbookEntries = enabledEntries;
} else {
- console.warn('[剧情优化大师] 未找到设置面板,世界书功能将回退到使用已保存的设置。');
+ // Panel is not ready or doesn't exist. Fall back to the saved settings from the extension.
+ // This uses the correct, prefixed keys.
+ if (panel.length > 0) {
+ console.warn('[剧情优化大师] 检测到UI面板但内容未完全加载,回退到使用已保存的设置。');
+ } else {
+ console.warn('[剧情优化大师] 未找到设置面板,世界书功能将使用已保存的设置。');
+ }
+
liveSettings = {
- worldbookEnabled: apiSettings.worldbookEnabled,
- worldbookSource: apiSettings.worldbookSource,
- selectedWorldbooks: apiSettings.selectedWorldbooks,
- worldbookCharLimit: apiSettings.worldbookCharLimit,
- enabledWorldbookEntries: apiSettings.enabledWorldbookEntries,
+ worldbookEnabled: apiSettings.plotOpt_worldbook_enabled,
+ worldbookSource: apiSettings.plotOpt_worldbook_source || 'character', // Default to 'character'
+ selectedWorldbooks: apiSettings.plotOpt_worldbook_selected_worldbooks,
+ worldbookCharLimit: apiSettings.plotOpt_worldbook_char_limit,
+ enabledWorldbookEntries: apiSettings.plotOpt_worldbook_selected_entries,
};
}
@@ -355,7 +354,8 @@ export async function getPlotOptimizedWorldbookContent(context, apiSettings) {
const userEnabledEntries = allEntries.filter(entry => {
if (!entry.enabled) return false;
const bookConfig = enabledEntriesMap[entry.bookName];
- return bookConfig ? bookConfig.includes(entry.uid) : false;
+ // 同时检查数字和字符串类型的UID,以兼容从实时UI(数字)和已保存设置(可能为字符串)中读取的配置
+ return bookConfig ? (bookConfig.includes(entry.uid) || bookConfig.includes(String(entry.uid))) : false;
});
if (userEnabledEntries.length === 0) return '';
@@ -363,8 +363,8 @@ export async function getPlotOptimizedWorldbookContent(context, apiSettings) {
const chatHistory = context.chat.map(message => message.mes).join('\n').toLowerCase();
const getEntryKeywords = (entry) => [...new Set([...(entry.key || []), ...(entry.keys || [])])].map(k => k.toLowerCase());
- const blueLightEntries = userEnabledEntries.filter(entry => entry.type === 'constant');
- let pendingGreenLights = userEnabledEntries.filter(entry => entry.type !== 'constant');
+ const blueLightEntries = userEnabledEntries.filter(entry => entry.constant);
+ let pendingGreenLights = userEnabledEntries.filter(entry => !entry.constant);
const triggeredEntries = new Set([...blueLightEntries]);
diff --git a/core/rag-processor.js b/core/rag-processor.js
index 426b26d..e98a495 100644
--- a/core/rag-processor.js
+++ b/core/rag-processor.js
@@ -1 +1 @@
-'use strict';const _0x58d31a=_0x53b6;function _0x1622(){const _0x44770a=['settingsVersion','[翰林院]\x20常规组返回\x20','unknown','part','substring','翰林院通告','\x22\x20已删除。','success','/api/vector/list',']\x20更正为\x20[','9770fBLQzy','toISOString','owner','queryMessageCount','在源作用域\x20\x27','rerank_score','stringify','status','[翰林院-日志]\x20所有知识库查询完毕,共获得\x20','\x20记录凝识范围:\x20','oldId','initialized','[翰林院-户口普查]\x20知识库\x20\x22','trim','key','[来源:\x20','includes','小说:','max','翰林院忆识核心已启动\x20(V5.2-集成版),已注册到全局\x20hanlinyuanRagProcessor\x20对象。','warning','[翰林院-核心]\x20凝识任务已锁定知识库:\x20','小说录入','floor','\x20条结果。','is_user','[翰林院-日志]\x20发送到\x20/api/vector/purge\x20的请求体:','未分类世界书',',将清空集合:\x20','message','296oKIudR','聊天记录','[翰林院-核心]\x20准备删除知识库\x20','test','HANLINYUAN_RAG_LOREBOOK','聊天记录\x20#','[翰林院-修复]\x20最终返回数组长度:\x20','[翰林院-核心]\x20已将\x20','用户取消了迁移操作','end','has','外部Rerank完成','toString','map','检测到旧版数据,正在进行一次性户口普查...','\x20个块。','\x27\x20中未找到ID为\x20','error','[翰林院-日志]\x20清空宝库API调用成功。','\x20的知识库。',',\x20第1卷,\x20第1章,\x20第','score','\x20列表API时出现问题\x20(状态:\x20','maxResults','[翰林院-日志]\x20统计集合\x20','POST','data','知识库名称不能为空','knowledgeBases','179090OcfiBh','[翰林院-计数]\x20在作用域\x20\x27','vectors_rearrangeChat','injection_','\x22,将数据合并入库。','chapter','所有启用库','keys','[翰林院-日志]\x20集合\x20','aborted','forEach','Rerank失败:\x20','42WlHeXY','start','json','scope','HANLINYUAN_RAG_CHAT','getRequestHeaders','手动录入:\x20','部分]','[翰林院]\x20最终无可用结果,注入中止。','hasOwnProperty','第1章','/api/vector/insert','[翰林院]\x20已从\x20','now','\x5c$&','[翰林院-日志]\x20清空目标集合ID:\x20',',\x20向量化录入时间:\x20','reranked','min','range','[翰林院-日志]\x20开始获取所有知识库的向量总数...','[翰林院-日志]\x20无法确定要清空的目标集合ID。','5951CTTLpp','\x20(集合ID:\x20','mes','comment','charCodeAt','\x22\x20创建专属知识库...','\x20条消息分解为\x20','\x0a','info','position','\x20不存在,计为\x200。','chat','hanlinyuanRagProcessor','[翰林院-日志]\x20统计目标集合ID:\x20','[翰林院]\x20常规池处理完毕,产出\x20','then','输入文本为空','source','[来源:\x20聊天记录,\x20楼层:\x20#','filter','sourceName','[翰林院-日志]\x20开始清空宝库...','查询集合\x20','[翰林院-核心]\x20成功插入\x20','newId','17115MIIeVx','local','[翰林院-日志]\x20/api/vector/purge\x20响应状态:\x20','[翰林院-日志]\x20正在查询知识库:\x20','novel','[翰林院-核心]\x20文本录入任务被用户中止。','[翰林院-核心]\x20成功删除知识库\x20','relevance_score','chat_history','[翰林院-户口普查]\x20检测到旧版设置\x20(V','[翰林院]\x20进入多路并行独立检索流程...','知识库\x20\x22','检测到旧版数据。此操作将把旧数据迁移到新格式,过程不可逆,是否继续?','对话记录小总结','正在处理\x20','\x27的文本分割成\x20','聊天记录:\x20','\x20返回\x20','depth','\x20个知识块,准备入库。','batchSize','_history','saveSettingsDebounced','[翰林院]\x20优先组\x20','depth_role','toLocaleString','5dCRGyr','string','tiaomu','entryName','sources','name','[翰林院-核心]\x20已锁定忆识宝库ID:\x20','[翰林院-核心]\x20已为角色\x20','rerank','startsWith','index','quiet','忆识检索失败:\x20','\x20不存在,返回空数组。','[翰林院-配置]\x20','\x27\x20的注入设置,跳过处理。','\x20(ID:\x20','superSortEnabled','HANLINYUAN_RAG_NOVEL','[翰林院-Rerank]\x20元数据加权排序完成。','忆识存入API错误\x20','[翰林院]\x20未能获取SillyTavern上下文,初始化失败。','warn','963918nHZCuH','webllm','[翰林院-日志]\x20获取集合\x20','[翰林院-核心]\x20文本录入失败:\x20','condensationHistory','clearJob','slice','bookName','catch','getTime','手动录入','original_index','reduce',',\x20条目:\x20','\x20个条目。','HANLINYUAN_RAG_MANUAL','hanlinyuan-rag-core','[翰林院-日志]\x20没有启用的新知识库,尝试查询旧版单体宝库...','_text}}','retrieval','bianzhuan','[翰林院-核心]\x20知识库\x20','[翰林院]\x20创建常规查询组\x20(','
$1','[翰林院]\x20创建优先查询组:\x20','移动失败:没有当前角色,无法移入局部知识库。','世界书','\x20个向量条目。','个库)','metadata','global','toLowerCase','(已锁定:\x20','微言录总结','enabled','小说:\x20','push','世界书条目','advanced','正在智能分块...','vector','\x20及其向量数据。','find','lorebook','log','379748NPvGyV','task_','flat','[翰林院-日志]\x20查询知识库\x20','replace','match','abs','27405tTGBRP','matchThreshold','extensionSettings','random','[翰林院-日志]\x20清空宝库API错误:','\x20(范围:\x20','AbortError','zh-CN','manual','统一检索部分的Rerank已完成','删除知识库失败,未能清空后端数据。','[翰林院-迁移]\x20用户取消了迁移操作。','旧版宝库\x20(Legacy)','[翰林院-核心]\x20聊天记录凝识失败:\x20','isArray','未知角色','[翰林院-配置]\x20为旧版知识库\x20','\x20个特定知识库。','\x22\x20已从\x20[','514728YaAESa','操作已取消。','condensation','results','/api/vector/query','[翰林院-核心]\x20ingestTextToHanlinyuan\x20失败:','sjshu','add','\x20池精确提取\x20','\x27\x20注入\x20','values','insertVectors\x20必须接收一个有效的\x20collectionId\x20参数。','[翰林院-Rerank]\x20外部Rerank失败,将仅使用内部加权。',',\x20第','legacy','[翰林院-核心]\x20准备为任务\x20\x22','priorityRetrieval','join','[翰林院-迁移]\x20集合\x20','凝识之权未开启','[翰林院-分块]\x20未知的来源类型\x20\x27','\x20时发生网络错误:','notify','length','text','移动失败:未找到源条目。','final_score','[翰林院]\x20最终准备注入\x20','[翰林院-日志]\x20查询白名单已提供,将查询\x20','】已成功移动到','[翰林院-修复]\x20最终返回数组样本:','\x20失败:\x20','无法确定要清空的目标宝库。','user','rearrangeChat','[翰林院-日志]\x20忆识存入API错误:','[翰林院-日志]\x20开始向量查询...\x20(目标:\x20','hashes',')\x20的状态已切换为:\x20','findIndex'];_0x1622=function(){return _0x44770a;};return _0x1622();}(function(_0x596dc9,_0x1b5a25){const _0x14a3a1=_0x53b6,_0x313834=_0x596dc9();while(!![]){try{const _0x42322b=parseInt(_0x14a3a1(0x1ef))/0x1*(parseInt(_0x14a3a1(0x19a))/0x2)+parseInt(_0x14a3a1(0x206))/0x3+-parseInt(_0x14a3a1(0x233))/0x4+parseInt(_0x14a3a1(0x23a))/0x5*(parseInt(_0x14a3a1(0x1a6))/0x6)+parseInt(_0x14a3a1(0x1d5))/0x7*(parseInt(_0x14a3a1(0x17d))/0x8)+parseInt(_0x14a3a1(0x24d))/0x9+-parseInt(_0x14a3a1(0x27f))/0xa*(parseInt(_0x14a3a1(0x1bc))/0xb);if(_0x42322b===_0x1b5a25)break;else _0x313834['push'](_0x313834['shift']());}catch(_0x3c946f){_0x313834['push'](_0x313834['shift']());}}}(_0x1622,0x50f29));import{extension_prompt_roles,setExtensionPrompt}from'/script.js';import*as _0x4b95b8 from'./utils/context-utils.js';import{getCollectionIdInfo,getCharacterId,getCharacterStableId}from'./utils/context-utils.js';import{defaultSettings as _0x2e18e9}from'./rag-settings.js';import*as _0x373cd3 from'./ingestion-manager.js';import{getEmbeddings,fetchEmbeddingModels as _0x1849a7,fetchRerankModels as _0x3bc1c3,executeRerank,testApiConnection as _0x30722b}from'./rag-api.js';import{superSort}from'./super-sorter.js';const MODULE_NAME=_0x58d31a(0x216),OFFICIAL_REARRANGE_CHAT_FUNCTION_NAME=_0x58d31a(0x19c),GLOBAL_SCOPE_ID='_global';let context=null,settings=null,lockedCollectionId=null;function filterWorldbooks(_0x539dec,_0x3a0bf1){const _0x59ffde=_0x58d31a;if(!_0x539dec||!_0x539dec[_0x59ffde(0x28c)]())return _0x3a0bf1;const _0x27dfd2=_0x539dec[_0x59ffde(0x225)]()[_0x59ffde(0x28c)]();return _0x3a0bf1['filter'](_0x39d823=>{const _0x4ecdc6=_0x59ffde;return _0x39d823[_0x4ecdc6(0x225)]()[_0x4ecdc6(0x28f)](_0x27dfd2)||containsPinyinMatch(_0x39d823,_0x27dfd2);});}function filterWorldbookEntries(_0x450631,_0x5ed999){const _0x2cd35c=_0x58d31a;if(!_0x450631||!_0x450631['trim']())return _0x5ed999;const _0x24b2dc=_0x450631[_0x2cd35c(0x225)]()[_0x2cd35c(0x28c)]();return _0x5ed999[_0x2cd35c(0x1cf)](_0x4ee205=>{const _0x5189ac=_0x2cd35c,_0x32842a=[_0x4ee205[_0x5189ac(0x1bf)]||'',_0x4ee205[_0x5189ac(0x28d)]||'',_0x4ee205['content']||''][_0x5189ac(0x25e)]('\x20')['toLowerCase']();return _0x32842a['includes'](_0x24b2dc)||containsPinyinMatch(_0x4ee205[_0x5189ac(0x1bf)]||'',_0x24b2dc);});}function containsPinyinMatch(_0x4c2bc4,_0x452a22){const _0x40548c=_0x58d31a,_0x40da67={'世界书':_0x40548c(0x253),'条目':_0x40548c(0x1f1),'编纂':_0x40548c(0x21a),'搜索':'sousuo'},_0x2c4c09=_0x40da67[_0x4c2bc4];return _0x2c4c09&&_0x2c4c09[_0x40548c(0x28f)](_0x452a22);}function highlightSearchMatch(_0x515c83,_0x266bdd){const _0x4a64b1=_0x58d31a;if(!_0x266bdd||!_0x266bdd['trim']())return _0x515c83;const _0x2a17fd=new RegExp('('+_0x266bdd[_0x4a64b1(0x237)](/[.*+?^${}()|[\]\\]/g,_0x4a64b1(0x1b4))+')','gi');return _0x515c83[_0x4a64b1(0x237)](_0x2a17fd,_0x4a64b1(0x21d));}function debounce(_0x5aa464,_0x5d6b00){let _0x5cbd9b;return function _0x51a303(..._0x45ab36){const _0x2196d3=()=>{clearTimeout(_0x5cbd9b),_0x5aa464(..._0x45ab36);};clearTimeout(_0x5cbd9b),_0x5cbd9b=setTimeout(_0x2196d3,_0x5d6b00);};}export{initialize,getSettings,saveSettings,resetSettings,_0x30722b as testApiConnection,_0x1849a7 as fetchEmbeddingModels,_0x3bc1c3 as fetchRerankModels,getVectorCount,purgeStorage,getMessagesForCondensation,processCondensation,ingestTextToHanlinyuan,getCollectionId,toggleSessionLock,isSessionLocked,getLockedSessionInfo,addKnowledgeBase,removeKnowledgeBase,getLocalKnowledgeBases,getGlobalKnowledgeBases,toggleKnowledgeBase,moveKnowledgeBase,filterWorldbooks,filterWorldbookEntries,highlightSearchMatch,debounce};function initialize(){const _0x41579c=_0x58d31a;context=SillyTavern['getContext']();if(!context){console[_0x41579c(0x18e)](_0x41579c(0x204));return;}settings=getSettings(),!window[_0x41579c(0x1c8)]&&(window[_0x41579c(0x1c8)]={}),window[_0x41579c(0x1c8)][_0x41579c(0x26f)]=rearrangeChat,window[_0x41579c(0x1c8)][_0x41579c(0x28a)]=!![],console['log'](_0x41579c(0x292));}async function ingestTextToHanlinyuan(_0x1d76c7,_0x382fcc=_0x58d31a(0x242),_0x23eb41={},_0x466453=()=>{},_0x32b9f4=null,_0xdee15b=()=>{},_0x56dd99=()=>{},_0x32cf6e=null,_0x2173be=0x0){const _0x4a4703=_0x58d31a;if(!_0x1d76c7||!_0x1d76c7[_0x4a4703(0x28c)]())return{'success':![],'error':_0x4a4703(0x1cc)};if(!settings)return{'success':![],'error':'核心未初始化'};try{const _0x37504d=getCollectionIdInfo(),_0x545a65=await _0x23dff3();if(_0x37504d['oldId']&&_0x37504d['oldId']===_0x545a65&&_0x37504d[_0x4a4703(0x289)]!==_0x37504d[_0x4a4703(0x1d4)]){const _0x57f18e=confirm(_0x4a4703(0x1e1));if(_0x57f18e)_0xdee15b('[翰林院-迁移]\x20用户确认迁移,正在处理旧宝库:\x20'+_0x37504d[_0x4a4703(0x289)],_0x4a4703(0x205)),await purgeStorage(_0x37504d['oldId']),_0xdee15b('[翰林院-迁移]\x20旧宝库已清空。',_0x4a4703(0x27c));else return _0xdee15b(_0x4a4703(0x245),_0x4a4703(0x1c4)),toastr['info'](_0x4a4703(0x24e)),{'success':![],'error':_0x4a4703(0x185)};}let _0xbf02df,_0x2ff584;const _0x61d7f9=new Date()['toLocaleString'](_0x4a4703(0x241),{'hour12':![]}),_0x1d5b37=getCharacterName()||_0x4a4703(0x249);switch(_0x382fcc){case'chat_history':const _0x466861=_0x23eb41[_0x4a4703(0x1b9)]||{},_0x15eead=_0x466861[_0x4a4703(0x1a7)]??'?',_0x1a5600=_0x466861[_0x4a4703(0x186)]===0x0?'末':_0x466861['end']??'?';_0xbf02df=_0x1d5b37+':\x20'+_0x15eead+'楼-'+_0x1a5600+'楼';break;case _0x4a4703(0x231):const _0x4cf7b6=_0x23eb41['bookName']||_0x4a4703(0x29a);if(_0x23eb41['entryName']&&_0x23eb41[_0x4a4703(0x1f2)][_0x4a4703(0x28f)](_0x4a4703(0x227)))_0x23eb41[_0x4a4703(0x1f2)]=_0x4a4703(0x1e2);else _0x23eb41[_0x4a4703(0x1f2)]&&_0x23eb41[_0x4a4703(0x1f2)][_0x4a4703(0x28f)]('宏史卷总结')&&(_0x23eb41['entryName']='对话记录大总结');const _0x5942c2=_0x23eb41[_0x4a4703(0x1f2)]||'未知条目';_0xbf02df=_0x4cf7b6+':\x20'+_0x5942c2;break;case'novel':_0xbf02df=_0x4a4703(0x229)+(_0x23eb41[_0x4a4703(0x1d0)]||'未知小说');break;case _0x4a4703(0x242):default:_0xbf02df=_0x4a4703(0x1ac)+_0x61d7f9;break;}const _0x131eb1=Object[_0x4a4703(0x257)](getKnowledgeBases()),_0x5b281a=_0x131eb1[_0x4a4703(0x230)](_0x2f6a9e=>_0x2f6a9e[_0x4a4703(0x1f4)]===_0xbf02df);if(_0x5b281a)_0x2ff584=_0x5b281a['id'],_0xdee15b('[翰林院-核心]\x20检测到同名知识库\x20\x22'+_0xbf02df+_0x4a4703(0x19e),'info');else{_0xdee15b('[翰林院-核心]\x20准备为任务\x20\x22'+_0xbf02df+_0x4a4703(0x1c1),'info');const _0x8934a7=addKnowledgeBase(_0xbf02df,_0x382fcc);_0x2ff584=_0x8934a7['id'];}const _0x1956ad=getCharacterStableId(),_0x3dda90=_0x1956ad+'_'+_0x2ff584;_0xdee15b('[翰林院-核心]\x20已创建并锁定知识库:\x20'+_0xbf02df+_0x4a4703(0x1bd)+_0x3dda90+')',_0x4a4703(0x27c)),_0xdee15b(_0x4a4703(0x1f5)+_0x3dda90,_0x4a4703(0x1c4)),_0x466453({'message':_0x4a4703(0x22d),'processed':0x0,'total':0x1});const _0x13af12=splitIntoChunks(_0x1d76c7,_0x382fcc,_0x23eb41),_0x3fe8c3=_0x13af12[_0x4a4703(0x264)];if(_0x32b9f4?.[_0x4a4703(0x1a3)])throw new Error('AbortError');_0xdee15b('[翰林院-核心]\x20将来源\x27'+_0xbf02df+_0x4a4703(0x1e4)+_0x3fe8c3+_0x4a4703(0x18c),_0x4a4703(0x1c4));if(_0x3fe8c3===0x0)return{'success':!![],'count':0x0};const _0x572f63=settings[_0x4a4703(0x219)][_0x4a4703(0x1e9)]||0x5;let _0x1be833=_0x2173be;for(let _0x254274=_0x2173be;_0x254274<_0x3fe8c3;_0x254274+=_0x572f63){if(_0x32b9f4?.[_0x4a4703(0x1a3)])throw new Error('AbortError');const _0x309ea1=_0x13af12[_0x4a4703(0x20c)](_0x254274,_0x254274+_0x572f63);_0x466453({'message':_0x4a4703(0x1e3)+(_0x254274+0x1)+'-'+(_0x254274+_0x309ea1[_0x4a4703(0x264)])+'\x20块','processed':_0x254274,'total':_0x3fe8c3});const _0x4bbcbb=_0x309ea1[_0x4a4703(0x18a)](_0x16dc9f=>_0x16dc9f[_0x4a4703(0x265)]),_0x130372=await getEmbeddings(_0x4bbcbb,_0x32b9f4);if(_0x32b9f4?.['aborted'])throw new Error(_0x4a4703(0x240));if(_0x309ea1[_0x4a4703(0x264)]!==_0x130372[_0x4a4703(0x264)])throw new Error('文本块和向量数量不匹配');const _0x5ee4f5=_0x309ea1[_0x4a4703(0x18a)]((_0x5e88ce,_0xaaa16)=>({..._0x5e88ce,'vector':_0x130372[_0xaaa16]}));await insertVectors(_0x5ee4f5,_0x32b9f4,_0x3dda90),_0x1be833+=_0x309ea1[_0x4a4703(0x264)],_0x32cf6e&&_0x373cd3['saveProgress'](_0x32cf6e,_0x1be833,_0x3fe8c3),await _0x56dd99();}return _0x32cf6e&&_0x373cd3[_0x4a4703(0x20b)](_0x32cf6e),_0xdee15b(_0x4a4703(0x1d3)+_0x1be833+_0x4a4703(0x221),_0x4a4703(0x27c)),{'success':!![],'count':_0x1be833};}catch(_0x1f0223){if(_0x1f0223[_0x4a4703(0x1f4)]===_0x4a4703(0x240)){_0xdee15b(_0x4a4703(0x1da),_0x4a4703(0x205));throw _0x1f0223;}return console[_0x4a4703(0x18e)](_0x4a4703(0x252),_0x1f0223),_0xdee15b(_0x4a4703(0x209)+_0x1f0223[_0x4a4703(0x17c)],'error'),{'success':![],'error':_0x1f0223[_0x4a4703(0x17c)]};}}function getSettings(){const _0x1fd69f=_0x58d31a;if(!context||!context[_0x1fd69f(0x23c)])return structuredClone(_0x2e18e9);let _0x2dadba=context['extensionSettings'][MODULE_NAME];!_0x2dadba&&(_0x2dadba={},context[_0x1fd69f(0x23c)][MODULE_NAME]=_0x2dadba);_0x2dadba[_0x1fd69f(0x20a)]===undefined&&(_0x2dadba[_0x1fd69f(0x20a)]={});_0x2dadba[_0x1fd69f(0x199)]===undefined&&(_0x2dadba['knowledgeBases']={});for(const _0x16fc98 in _0x2e18e9){if(_0x2dadba[_0x16fc98]===undefined)_0x2dadba[_0x16fc98]=structuredClone(_0x2e18e9[_0x16fc98]);else{if(typeof _0x2e18e9[_0x16fc98]==='object'&&!Array['isArray'](_0x2e18e9[_0x16fc98])&&_0x2e18e9[_0x16fc98]!==null)for(const _0x209e6b in _0x2e18e9[_0x16fc98]){_0x2dadba[_0x16fc98][_0x209e6b]===undefined&&(_0x2dadba[_0x16fc98][_0x209e6b]=_0x2e18e9[_0x16fc98][_0x209e6b]);}}}return _0x2dadba;}function saveSettings(){const _0x555599=_0x58d31a;if(context)context[_0x555599(0x1eb)]();}function resetSettings(){context&&(context['extensionSettings'][MODULE_NAME]=structuredClone(_0x2e18e9),saveSettings());}function showNotification(_0x2cb3cd,_0x38f328=_0x58d31a(0x1c4)){toastr[_0x38f328](_0x2cb3cd);}function getTagForSource(_0xfef1de){const _0x4084eb=_0x58d31a;switch(_0xfef1de){case _0x4084eb(0x1dd):return _0x4084eb(0x17e);case'lorebook':return _0x4084eb(0x220);case _0x4084eb(0x242):return'手动录入';case _0x4084eb(0x1d9):return _0x4084eb(0x295);default:return'资料';}}function splitIntoChunks(_0x2d938c,_0x200900,_0x351e70={}){const _0xc05d27=_0x58d31a;switch(_0x200900){case _0xc05d27(0x1d9):return _chunkForNovel(_0x2d938c,_0x351e70);case'chat_history':return _chunkForChatHistory(_0x2d938c,_0x351e70);case'lorebook':return _chunkForLorebook(_0x2d938c,_0x351e70);case'manual':return _chunkForManual(_0x2d938c,_0x351e70);default:console[_0xc05d27(0x205)](_0xc05d27(0x261)+_0x200900+'\x27,使用通用分块逻辑。');return _chunkForManual(_0x2d938c,{..._0x351e70,'sourceName':_0x351e70[_0xc05d27(0x1d0)]||'未知来源'});}}function _chunkForNovel(_0x325958,_0xce1e7b){const _0x2c8441=_0x58d31a,{chunkSize:_0x13f95e,overlap:_0x14e5f0}=settings[_0x2c8441(0x22c)],{sourceName:sourceName='小说'}=_0xce1e7b,_0x4e86ac=[];if(!_0x325958||_0x13f95e<=0x0)return _0x4e86ac;const _0x52b9ce=/(第\s*[一二三四五六七八九十百千万零\d]+\s*卷)/gim,_0x3250c6=/(第\s*[一二三四五六七八九十百千万零\d]+\s*[章回节部])|^(Chapter\s+\d+)/gim;let _0x1e061f=0x0;const _0xa9849d=_0x325958['split']('\x0a');let _0x56b681='第1卷',_0x241726='第1章',_0x50ed63=[];function _0x238a47(){const _0x4d89ff=_0x2c8441;if(_0x50ed63[_0x4d89ff(0x264)]===0x0)return;const _0x35b7f4=_0x50ed63['join']('\x0a');let _0x387535=0x0,_0x1b9f8a=0x1;while(_0x387535<_0x35b7f4[_0x4d89ff(0x264)]){const _0x14aa58=Math[_0x4d89ff(0x1b8)](_0x387535+_0x13f95e,_0x35b7f4[_0x4d89ff(0x264)]),_0xa0409e=_0x35b7f4[_0x4d89ff(0x279)](_0x387535,_0x14aa58);if(_0xa0409e[_0x4d89ff(0x28c)]()[_0x4d89ff(0x264)]>0x0){const _0x260cc4={'source':_0x4d89ff(0x1d9),'sourceName':sourceName,'timestamp':new Date()[_0x4d89ff(0x280)](),'globalIndex':_0x1e061f++,'volume':_0x56b681,'chapter':_0x241726,'section':_0x1b9f8a},_0x53fc9a=getTagForSource('novel'),_0x32e214=_0x4d89ff(0x28e)+sourceName+',\x20'+_0x56b681+',\x20'+_0x241726+',\x20第'+_0x1b9f8a+'节]',_0x3a56c2='<'+_0x53fc9a+'>\x0a'+_0x32e214+'\x0a'+_0xa0409e+_0x4d89ff(0x1c3)+_0x53fc9a+'>';_0x4e86ac[_0x4d89ff(0x22a)]({'text':_0x3a56c2,'metadata':_0x260cc4}),_0x1b9f8a++;}_0x387535+=_0x13f95e-_0x14e5f0;if(_0x387535>=_0x35b7f4[_0x4d89ff(0x264)])break;}_0x50ed63=[];}for(const _0x171b95 of _0xa9849d){const _0x4e6fc0=_0x171b95[_0x2c8441(0x28c)]();if(_0x52b9ce[_0x2c8441(0x180)](_0x4e6fc0))_0x238a47(),_0x56b681=_0x4e6fc0,_0x241726='第1章';else _0x3250c6[_0x2c8441(0x180)](_0x4e6fc0)?(_0x238a47(),_0x241726=_0x4e6fc0):_0x50ed63[_0x2c8441(0x22a)](_0x171b95);}_0x238a47();if(_0x4e86ac[_0x2c8441(0x264)]===0x0&&_0x325958[_0x2c8441(0x264)]>0x0){let _0x175af8=0x0,_0x45b5b7=0x1;while(_0x175af8<_0x325958[_0x2c8441(0x264)]){const _0x3722c5=Math[_0x2c8441(0x1b8)](_0x175af8+_0x13f95e,_0x325958[_0x2c8441(0x264)]),_0x427030=_0x325958[_0x2c8441(0x279)](_0x175af8,_0x3722c5),_0x348198={'source':_0x2c8441(0x1d9),'sourceName':sourceName,'timestamp':new Date()['toISOString'](),'globalIndex':_0x4e86ac[_0x2c8441(0x264)],'volume':'第1卷','chapter':_0x2c8441(0x1b0),'section':_0x45b5b7},_0x4a6e44=getTagForSource('novel'),_0x30c90f=_0x2c8441(0x28e)+sourceName+_0x2c8441(0x191)+_0x45b5b7+'节]',_0x5c75f1='<'+_0x4a6e44+'>\x0a'+_0x30c90f+'\x0a'+_0x427030+'\x0a'+_0x4a6e44+'>';_0x4e86ac[_0x2c8441(0x22a)]({'text':_0x5c75f1,'metadata':_0x348198}),_0x45b5b7++,_0x175af8+=_0x13f95e-_0x14e5f0;}}return _0x4e86ac;}function _chunkForChatHistory(_0x406a5a,_0x1ae9c4){const _0x5eb32a=_0x58d31a,{chunkSize:_0x4de07c,overlap:_0x5db0f3}=settings['advanced'],{floor:_0x326a0c,is_user:_0x4f1d7d,timestamp:_0x5b402b}=_0x1ae9c4,_0x310555=[];if(!_0x406a5a||_0x4de07c<=0x0)return _0x310555;let _0x7174cc=0x1,_0x250368=0x0;while(_0x250368<_0x406a5a[_0x5eb32a(0x264)]){const _0x5e42f3=Math['min'](_0x250368+_0x4de07c,_0x406a5a[_0x5eb32a(0x264)]),_0x3aaeb5=_0x406a5a[_0x5eb32a(0x279)](_0x250368,_0x5e42f3),_0xd4b1b8=_0x5eb32a(0x1ce)+_0x326a0c+_0x5eb32a(0x25a)+_0x7174cc+_0x5eb32a(0x1ad),_0x33434e=getTagForSource(_0x5eb32a(0x1dd)),_0x9bdbbc='<'+_0x33434e+'>\x0a'+_0xd4b1b8+'\x0a'+_0x3aaeb5+'\x0a'+_0x33434e+'>';_0x310555[_0x5eb32a(0x22a)]({'text':_0x9bdbbc,'metadata':{'source':'chat_history','sourceName':_0x5eb32a(0x182)+_0x326a0c,'floor':_0x326a0c,'part':_0x7174cc,'is_user':_0x4f1d7d,'timestamp':_0x5b402b}}),_0x7174cc++,_0x250368+=_0x4de07c-_0x5db0f3;if(_0x250368>=_0x406a5a[_0x5eb32a(0x264)])break;}return _0x310555;}function _chunkForLorebook(_0xa8717a,_0xc4601){const _0x154a55=_0x58d31a,{chunkSize:_0x1cbeb8,overlap:_0x13228a}=settings['advanced'],{bookName:bookName=_0x154a55(0x220),entryName:entryName=_0x154a55(0x22b)}=_0xc4601,_0x16c118=[];if(!_0xa8717a||_0x1cbeb8<=0x0)return _0x16c118;let _0x1092cc=0x1,_0x533672=0x0;while(_0x533672<_0xa8717a[_0x154a55(0x264)]){const _0xfbe3dc=Math[_0x154a55(0x1b8)](_0x533672+_0x1cbeb8,_0xa8717a[_0x154a55(0x264)]),_0x347ad2=_0xa8717a[_0x154a55(0x279)](_0x533672,_0xfbe3dc),_0x3d4f24=_0x154a55(0x28e)+bookName+_0x154a55(0x213)+entryName+',\x20第'+_0x1092cc+_0x154a55(0x1ad),_0xb252d6=getTagForSource(_0x154a55(0x231)),_0x43ee5d='<'+_0xb252d6+'>\x0a'+_0x3d4f24+'\x0a'+_0x347ad2+_0x154a55(0x1c3)+_0xb252d6+'>';_0x16c118[_0x154a55(0x22a)]({'text':_0x43ee5d,'metadata':{'source':_0x154a55(0x231),'sourceName':bookName+':\x20'+entryName,'bookName':bookName,'entryName':entryName,'part':_0x1092cc,'timestamp':new Date()['toISOString']()}}),_0x1092cc++,_0x533672+=_0x1cbeb8-_0x13228a;if(_0x533672>=_0xa8717a[_0x154a55(0x264)])break;}return _0x16c118;}function _chunkForManual(_0x3485b0,_0x38a717){const _0x5dc93e=_0x58d31a,{chunkSize:_0x20b9f1,overlap:_0x5d44dd}=settings[_0x5dc93e(0x22c)],{sourceName:sourceName=_0x5dc93e(0x210)}=_0x38a717,_0x31c8c5=[];if(!_0x3485b0||_0x20b9f1<=0x0)return _0x31c8c5;const _0x5061b7=new Date(),_0x7a759c=_0x5061b7[_0x5dc93e(0x1ee)](_0x5dc93e(0x241));let _0x3aa5d0=0x1,_0x5f567f=0x0;while(_0x5f567f<_0x3485b0[_0x5dc93e(0x264)]){const _0x4e57c7=Math['min'](_0x5f567f+_0x20b9f1,_0x3485b0[_0x5dc93e(0x264)]),_0x5b96c9=_0x3485b0['substring'](_0x5f567f,_0x4e57c7),_0x1708fe='[来源:\x20'+sourceName+_0x5dc93e(0x1b6)+_0x7a759c+_0x5dc93e(0x25a)+_0x3aa5d0+_0x5dc93e(0x1ad),_0xdb8f6d=getTagForSource('manual'),_0x2bc1cd='<'+_0xdb8f6d+'>\x0a'+_0x1708fe+'\x0a'+_0x5b96c9+_0x5dc93e(0x1c3)+_0xdb8f6d+'>';_0x31c8c5[_0x5dc93e(0x22a)]({'text':_0x2bc1cd,'metadata':{'source':_0x5dc93e(0x242),'sourceName':sourceName,'part':_0x3aa5d0,'timestamp':_0x5061b7[_0x5dc93e(0x280)]()}}),_0x3aa5d0++,_0x5f567f+=_0x20b9f1-_0x5d44dd;if(_0x5f567f>=_0x3485b0[_0x5dc93e(0x264)])break;}return _0x31c8c5;}import{getCollectionId as _0x23dff3,getCharacterName}from'./utils/context-utils.js';async function getCollectionId(){return lockedCollectionId||await _0x23dff3();}async function toggleSessionLock(){return lockedCollectionId?(lockedCollectionId=null,![]):(lockedCollectionId=await _0x23dff3(),!![]);}function isSessionLocked(){return lockedCollectionId!==null;}function getLockedSessionInfo(){const _0x501c8b=_0x58d31a;if(!lockedCollectionId)return null;return{'id':lockedCollectionId,'name':_0x501c8b(0x226)+lockedCollectionId[_0x501c8b(0x279)](0x0,0x8)+'...)'};}function getLocalKnowledgeBases(){const _0x34d31c=_0x58d31a,_0x43dcac=getCharacterStableId();return!settings[_0x34d31c(0x199)][_0x43dcac]&&(settings[_0x34d31c(0x199)][_0x43dcac]={}),settings[_0x34d31c(0x199)][_0x43dcac];}function getGlobalKnowledgeBases(){const _0x339e72=_0x58d31a;return!settings[_0x339e72(0x199)][GLOBAL_SCOPE_ID]&&(settings[_0x339e72(0x199)][GLOBAL_SCOPE_ID]={}),settings[_0x339e72(0x199)][GLOBAL_SCOPE_ID];}function getKnowledgeBases(){const _0x22bc0a=getLocalKnowledgeBases(),_0x198fce=getGlobalKnowledgeBases();return{..._0x198fce,..._0x22bc0a};}function addKnowledgeBase(_0x257e43,_0x158af9='manual'){const _0xf07685=_0x58d31a;if(!_0x257e43||!_0x257e43['trim']())throw new Error(_0xf07685(0x198));const _0x5d6491=getCharacterStableId(),_0x2362ac=getLocalKnowledgeBases(),_0x15a996=_0xf07685(0x234)+Date[_0xf07685(0x1b3)]()+'_'+Math[_0xf07685(0x23d)]()[_0xf07685(0x189)](0x24)[_0xf07685(0x279)](0x2,0x9),_0x2dba56={'id':_0x15a996,'name':_0x257e43[_0xf07685(0x28c)](),'enabled':!![],'createdAt':new Date()[_0xf07685(0x280)](),'owner':_0x5d6491,'source':_0x158af9};return _0x2362ac[_0x15a996]=_0x2dba56,saveSettings(),console[_0xf07685(0x232)](_0xf07685(0x1f6)+_0x5d6491+'\x20添加新知识库:\x20'+_0x257e43+_0xf07685(0x1ff)+_0x15a996+')'),_0x2dba56;}async function removeKnowledgeBase(_0x2701bc,_0x23e100){const _0x51dbe8=_0x58d31a,_0x17a79d=getCharacterStableId(),_0x49461c=_0x23e100===_0x51dbe8(0x224)?getGlobalKnowledgeBases():getLocalKnowledgeBases(),_0x2dc46c=_0x49461c[_0x2701bc],_0x294eb1=_0x2dc46c?.['name']||_0x2701bc;if(!_0x2dc46c){console[_0x51dbe8(0x205)]('[翰林院-核心]\x20尝试删除一个不存在的知识库:\x20'+_0x2701bc+_0x51dbe8(0x23f)+_0x23e100+')');return;}const _0x17e58e=_0x23e100===_0x51dbe8(0x224)?_0x2dc46c[_0x51dbe8(0x281)]||GLOBAL_SCOPE_ID:_0x17a79d,_0x1c60db=_0x17e58e+'_'+_0x2701bc;console['log'](_0x51dbe8(0x17f)+_0x2701bc+_0x51dbe8(0x17b)+_0x1c60db);const _0x177240=await purgeStorage(_0x1c60db);_0x177240?(delete _0x49461c[_0x2701bc],saveSettings(),console[_0x51dbe8(0x232)](_0x51dbe8(0x1db)+_0x2701bc+_0x51dbe8(0x22f)),toastr[_0x51dbe8(0x27c)](_0x51dbe8(0x1e0)+_0x294eb1+_0x51dbe8(0x27b))):(console[_0x51dbe8(0x18e)]('[翰林院-核心]\x20清空向量集合\x20'+_0x1c60db+'\x20失败,删除操作中止。'),toastr['error'](_0x51dbe8(0x244)));}function toggleKnowledgeBase(_0x1ac22c,_0x10e82c){const _0x435bf0=_0x58d31a,_0xea3a6d=_0x10e82c===_0x435bf0(0x224)?getGlobalKnowledgeBases():getLocalKnowledgeBases();_0xea3a6d[_0x1ac22c]&&(_0xea3a6d[_0x1ac22c][_0x435bf0(0x228)]=!_0xea3a6d[_0x1ac22c][_0x435bf0(0x228)],saveSettings(),console[_0x435bf0(0x232)](_0x435bf0(0x21b)+_0x1ac22c+_0x435bf0(0x23f)+_0x10e82c+_0x435bf0(0x273)+(_0xea3a6d[_0x1ac22c][_0x435bf0(0x228)]?'启用':'禁用')));}function generateHash(_0x4773c8){const _0x167c79=_0x58d31a;let _0x1467cf=0x0;for(let _0x361110=0x0;_0x361110<_0x4773c8['length'];_0x361110++){const _0x1ef1e6=_0x4773c8[_0x167c79(0x1c0)](_0x361110);_0x1467cf=(_0x1467cf<<0x5)-_0x1467cf+_0x1ef1e6,_0x1467cf=_0x1467cf&_0x1467cf;}return Math[_0x167c79(0x239)](_0x1467cf)['toString'](0x24);}function _0x53b6(_0x470fb9,_0x1fd1c9){const _0x1622f5=_0x1622();return _0x53b6=function(_0x53b69d,_0x3469c5){_0x53b69d=_0x53b69d-0x17b;let _0x14e9bf=_0x1622f5[_0x53b69d];return _0x14e9bf;},_0x53b6(_0x470fb9,_0x1fd1c9);}async function queryVectors(_0x5b0b6d,_0x456ef5={}){const _0x170b01=_0x58d31a,{includeBases:includeBases=null}=_0x456ef5;console['log'](_0x170b01(0x271)+(includeBases?'指定知识库':_0x170b01(0x1a0))+')');const _0x8a8278=getCharacterStableId();let _0x2cf293;if(includeBases)_0x2cf293=includeBases,console[_0x170b01(0x232)](_0x170b01(0x269)+_0x2cf293[_0x170b01(0x264)]+_0x170b01(0x24b));else{const _0x3905b6=getLocalKnowledgeBases(),_0x1d3e32=getGlobalKnowledgeBases(),_0x2bda21=Object[_0x170b01(0x257)](_0x3905b6)[_0x170b01(0x1cf)](_0x38bada=>_0x38bada[_0x170b01(0x228)]),_0xe9c8fc=Object[_0x170b01(0x257)](_0x1d3e32)[_0x170b01(0x1cf)](_0x522f2b=>_0x522f2b[_0x170b01(0x228)]);_0x2cf293=[..._0x2bda21['map'](_0x1f4684=>({..._0x1f4684,'scope':'local'})),..._0xe9c8fc[_0x170b01(0x18a)](_0x544079=>({..._0x544079,'scope':'global'}))];}if(_0x2cf293[_0x170b01(0x264)]===0x0&&!includeBases){console['log'](_0x170b01(0x217));const _0x524db3=await _0x23dff3();if(!_0x524db3)return[];_0x2cf293[_0x170b01(0x22a)]({'id':null,'name':_0x170b01(0x246),'scope':'legacy'});}if(_0x2cf293['length']===0x0)return console[_0x170b01(0x232)]('[翰林院-日志]\x20没有可供查询的知识库,查询中止。'),[];const _0x5696c1=(await getEmbeddings([_0x5b0b6d]))[0x0];if(!_0x5696c1)throw new Error('未能生成查询向量。');let _0x9644f=[];const _0x22a314=_0x2cf293['map'](_0x4e0a58=>{const _0x20aeeb=_0x170b01;let _0x5570dc;if(_0x4e0a58[_0x20aeeb(0x1a9)]===_0x20aeeb(0x25b))_0x5570dc=_0x23dff3();else{const _0x1c3540=_0x4e0a58[_0x20aeeb(0x1a9)]===_0x20aeeb(0x224)?_0x4e0a58[_0x20aeeb(0x281)]||GLOBAL_SCOPE_ID:_0x8a8278;_0x5570dc=Promise['resolve'](_0x1c3540+'_'+_0x4e0a58['id']);}return _0x5570dc[_0x20aeeb(0x1cb)](_0x49584e=>{const _0x337bb4=_0x20aeeb;if(!_0x49584e)return[];console[_0x337bb4(0x232)](_0x337bb4(0x1d8)+_0x4e0a58['name']+'\x20(ID:\x20'+_0x49584e+')');const _0x33a6f1={'collectionId':_0x49584e,'searchText':_0x5b0b6d,'topK':settings[_0x337bb4(0x22c)][_0x337bb4(0x194)],'threshold':settings[_0x337bb4(0x22c)][_0x337bb4(0x23b)],'source':_0x337bb4(0x207),'embeddings':{[_0x5b0b6d]:_0x5696c1}};return fetch(_0x337bb4(0x251),{'method':_0x337bb4(0x196),'headers':context[_0x337bb4(0x1ab)](),'body':JSON[_0x337bb4(0x285)](_0x33a6f1)})[_0x337bb4(0x1cb)](async _0x44b22c=>{const _0x3fa4e9=_0x337bb4;if(!_0x44b22c['ok']){const _0x448b70=await _0x44b22c[_0x3fa4e9(0x265)]();return console[_0x3fa4e9(0x18e)](_0x3fa4e9(0x236)+_0x49584e+'\x20失败:',_0x448b70),[];}const _0x1a89e6=await _0x44b22c['json']();let _0x32ebd7=[];if(Array['isArray'](_0x1a89e6))_0x32ebd7=_0x1a89e6;else{if(_0x1a89e6&&_0x1a89e6[_0x3fa4e9(0x223)]&&Array[_0x3fa4e9(0x248)](_0x1a89e6[_0x3fa4e9(0x223)]))_0x32ebd7=_0x1a89e6[_0x3fa4e9(0x223)];else{if(_0x1a89e6&&_0x1a89e6['results']&&Array[_0x3fa4e9(0x248)](_0x1a89e6[_0x3fa4e9(0x250)]))_0x32ebd7=_0x1a89e6['results'];else _0x1a89e6&&_0x1a89e6[_0x3fa4e9(0x197)]&&Array[_0x3fa4e9(0x248)](_0x1a89e6[_0x3fa4e9(0x197)])&&(_0x32ebd7=_0x1a89e6[_0x3fa4e9(0x197)]);}}const _0xd2bf7=_0x32ebd7[_0x3fa4e9(0x18a)](_0x46dc1f=>{const _0x3d832b=_0x3fa4e9;if(!_0x46dc1f||typeof _0x46dc1f[_0x3d832b(0x265)]!==_0x3d832b(0x1f0))return null;const _0x14fd9d={'source':_0x3d832b(0x277),'sourceName':'未知'},_0x460a1a=_0x46dc1f[_0x3d832b(0x265)]['match'](/^<([^>]+)>/),_0x3c6968=_0x460a1a?_0x460a1a[0x1]:'';switch(_0x3c6968){case _0x3d832b(0x17e):_0x14fd9d[_0x3d832b(0x1cd)]='chat_history';const _0x2c7823=_0x46dc1f['text'][_0x3d832b(0x238)](/楼层:\s*#(\d+),\s*第(\d+)部分/);_0x2c7823&&_0x2c7823[0x1]&&_0x2c7823[0x2]&&(_0x14fd9d[_0x3d832b(0x296)]=parseInt(_0x2c7823[0x1],0xa),_0x14fd9d[_0x3d832b(0x278)]=parseInt(_0x2c7823[0x2],0xa),_0x14fd9d['sourceName']='聊天记录\x20#'+_0x14fd9d[_0x3d832b(0x296)]);break;case'世界书':_0x14fd9d[_0x3d832b(0x1cd)]=_0x3d832b(0x231);const _0x1dfae1=_0x46dc1f[_0x3d832b(0x265)][_0x3d832b(0x238)](/\[来源:\s*([^,]+),\s*条目:\s*([^,]+),\s*第(\d+)部分\]/);_0x1dfae1&&_0x1dfae1[0x1]&&_0x1dfae1[0x2]&&_0x1dfae1[0x3]&&(_0x14fd9d[_0x3d832b(0x20d)]=_0x1dfae1[0x1][_0x3d832b(0x28c)](),_0x14fd9d[_0x3d832b(0x1f2)]=_0x1dfae1[0x2][_0x3d832b(0x28c)](),_0x14fd9d[_0x3d832b(0x278)]=parseInt(_0x1dfae1[0x3],0xa),_0x14fd9d[_0x3d832b(0x1d0)]=_0x14fd9d['bookName']+':\x20'+_0x14fd9d['entryName']);break;case _0x3d832b(0x210):_0x14fd9d[_0x3d832b(0x1cd)]='manual';const _0x4f75ab=_0x46dc1f[_0x3d832b(0x265)]['match'](/\[来源:\s*([^,]+),.*第(\d+)部分\]/);_0x4f75ab&&_0x4f75ab[0x1]&&_0x4f75ab[0x2]&&(_0x14fd9d[_0x3d832b(0x1d0)]=_0x4f75ab[0x1][_0x3d832b(0x28c)](),_0x14fd9d['part']=parseInt(_0x4f75ab[0x2],0xa));break;case'小说录入':_0x14fd9d[_0x3d832b(0x1cd)]=_0x3d832b(0x1d9);const _0x3a1bea=_0x46dc1f[_0x3d832b(0x265)][_0x3d832b(0x238)](/\[来源:\s*([^,]+),\s*([^,]+),\s*([^,]+),\s*([^\]]+)\]/);_0x3a1bea&&(_0x14fd9d[_0x3d832b(0x1d0)]=_0x3a1bea[0x1][_0x3d832b(0x28c)](),_0x14fd9d['volume']=_0x3a1bea[0x2][_0x3d832b(0x28c)](),_0x14fd9d[_0x3d832b(0x19f)]=_0x3a1bea[0x3][_0x3d832b(0x28c)](),_0x14fd9d['section']=_0x3a1bea[0x4][_0x3d832b(0x28c)]());break;}return{..._0x46dc1f,'score':_0x46dc1f['score']||0x1,'metadata':_0x14fd9d};})[_0x3fa4e9(0x1cf)](Boolean);return console[_0x3fa4e9(0x232)]('[翰林院-V13\x20修复]\x20重建元数据后,知识库\x20'+_0x4e0a58[_0x3fa4e9(0x1f4)]+_0x3fa4e9(0x1e6)+_0xd2bf7[_0x3fa4e9(0x264)]+_0x3fa4e9(0x297)),_0xd2bf7;})[_0x337bb4(0x20e)](_0x203e08=>{const _0x296a67=_0x337bb4;return console[_0x296a67(0x18e)](_0x296a67(0x236)+_0x49584e+_0x296a67(0x262),_0x203e08),[];});});}),_0x58976c=await Promise['all'](_0x22a314);_0x9644f=_0x58976c[_0x170b01(0x235)](),console[_0x170b01(0x232)](_0x170b01(0x287)+_0x9644f['length']+'\x20条初步结果。');const _0x4fbdd5=[],_0x4a603e=new Set();for(const _0x466c38 of _0x9644f){if(_0x466c38&&typeof _0x466c38==='object'&&_0x466c38[_0x170b01(0x265)]&&typeof _0x466c38[_0x170b01(0x265)]===_0x170b01(0x1f0)){const _0x24e5df=_0x466c38[_0x170b01(0x265)]['trim']();_0x24e5df[_0x170b01(0x264)]>0x0&&!_0x4a603e[_0x170b01(0x187)](_0x24e5df)&&(_0x4a603e[_0x170b01(0x254)](_0x24e5df),_0x4fbdd5[_0x170b01(0x22a)](_0x466c38));}}console[_0x170b01(0x232)]('[翰林院-日志]\x20去重后剩余\x20'+_0x4fbdd5[_0x170b01(0x264)]+'\x20条结果。'),_0x4fbdd5['sort']((_0xca3a1d,_0x5262c5)=>(_0x5262c5[_0x170b01(0x192)]||0x0)-(_0xca3a1d['score']||0x0));const _0x3c8ac3=[..._0x4fbdd5];return console[_0x170b01(0x232)](_0x170b01(0x183)+_0x3c8ac3[_0x170b01(0x264)]),console[_0x170b01(0x232)](_0x170b01(0x26b),JSON[_0x170b01(0x285)](_0x3c8ac3['slice'](0x0,0x1),null,0x2)),_0x3c8ac3;}async function insertVectors(_0x2393c8,_0x2f9422=null,_0x279c29){const _0x46de9c=_0x58d31a;if(!_0x279c29)throw new Error(_0x46de9c(0x258));if(_0x2393c8['length']===0x0)return{'success':!![],'count':0x0};const _0x5476c6=_0x2393c8[_0x46de9c(0x18a)]((_0x37c82c,_0x4d68ed)=>({'hash':generateHash(_0x37c82c['text']+Date[_0x46de9c(0x1b3)]()+_0x4d68ed),'text':_0x37c82c[_0x46de9c(0x265)],'metadata':_0x37c82c[_0x46de9c(0x223)]||{'source':'unknown','timestamp':new Date()[_0x46de9c(0x280)]()}})),_0x559ae3=_0x5476c6[_0x46de9c(0x212)]((_0x11507f,_0x278ca8,_0xa75533)=>{const _0x3c5c3d=_0x46de9c;return _0x11507f[_0x278ca8[_0x3c5c3d(0x265)]]=_0x2393c8[_0xa75533][_0x3c5c3d(0x22e)],_0x11507f;},{}),_0x1b0009={'collectionId':_0x279c29,'items':_0x5476c6,'source':'webllm','embeddings':_0x559ae3},_0x2042dc=await fetch(_0x46de9c(0x1b1),{'method':'POST','headers':context[_0x46de9c(0x1ab)](),'body':JSON[_0x46de9c(0x285)](_0x1b0009),'signal':_0x2f9422});if(!_0x2042dc['ok']){const _0xa10c50=await _0x2042dc[_0x46de9c(0x265)]();console[_0x46de9c(0x18e)](_0x46de9c(0x270),_0xa10c50);throw new Error(_0x46de9c(0x203)+_0x2042dc[_0x46de9c(0x286)]+':\x20'+_0xa10c50);}return{'success':!![],'count':_0x5476c6[_0x46de9c(0x264)]};}async function getVectorCount(_0x2924cb=null,_0x15f890=_0x58d31a(0x1d6)){const _0x2e4bdf=_0x58d31a,_0x8516ab=getCharacterStableId();if(_0x2924cb){const _0x4774b3=_0x15f890===_0x2e4bdf(0x224)?getGlobalKnowledgeBases():getLocalKnowledgeBases(),_0x5b5ed1=_0x4774b3[_0x2924cb];if(!_0x5b5ed1)return console['warn'](_0x2e4bdf(0x19b)+_0x15f890+_0x2e4bdf(0x18d)+_0x2924cb+_0x2e4bdf(0x190)),0x0;const _0x57be13=_0x15f890===_0x2e4bdf(0x224)?_0x5b5ed1['owner']||GLOBAL_SCOPE_ID:_0x8516ab,_0xd38398=_0x57be13+'_'+_0x2924cb;return await countVectorsInCollection(_0xd38398);}else{console[_0x2e4bdf(0x232)](_0x2e4bdf(0x1ba));const _0x1a5e58=Object['values'](getLocalKnowledgeBases()),_0x37c711=Object['values'](getGlobalKnowledgeBases()),_0x154ae9=[];_0x1a5e58[_0x2e4bdf(0x1a4)](_0x3eef14=>{const _0x3c9702=_0x2e4bdf,_0x1e13b9=_0x8516ab+'_'+_0x3eef14['id'];_0x154ae9[_0x3c9702(0x22a)](countVectorsInCollection(_0x1e13b9));}),_0x37c711['forEach'](_0x52a073=>{const _0x5edfb8=_0x2e4bdf,_0x7b0c80=_0x52a073[_0x5edfb8(0x281)]||GLOBAL_SCOPE_ID,_0x55ae72=_0x7b0c80+'_'+_0x52a073['id'];_0x154ae9[_0x5edfb8(0x22a)](countVectorsInCollection(_0x55ae72));});const _0x357fd3=await _0x23dff3();_0x154ae9[_0x2e4bdf(0x22a)](countVectorsInCollection(_0x357fd3));const _0x540cf1=await Promise['all'](_0x154ae9),_0x1582a4=_0x540cf1['reduce']((_0x211a7b,_0x2dcdbe)=>_0x211a7b+_0x2dcdbe,0x0);return console[_0x2e4bdf(0x232)]('[翰林院-日志]\x20所有知识库统计完成,总向量数:\x20'+_0x1582a4),_0x1582a4;}}async function countVectorsInCollection(_0x4f6a19){const _0x1a7a8a=_0x58d31a;if(!_0x4f6a19)return 0x0;console[_0x1a7a8a(0x232)](_0x1a7a8a(0x1c9)+_0x4f6a19);const _0x1ba29d={'collectionId':_0x4f6a19,'source':_0x1a7a8a(0x207),'embeddings':{}};try{const _0x32ade5=await fetch(_0x1a7a8a(0x27d),{'method':_0x1a7a8a(0x196),'headers':context['getRequestHeaders'](),'body':JSON[_0x1a7a8a(0x285)](_0x1ba29d)});if(!_0x32ade5['ok']){if(_0x32ade5['status']===0x194)console[_0x1a7a8a(0x232)](_0x1a7a8a(0x1a2)+_0x4f6a19+_0x1a7a8a(0x1c6));else{const _0x1922bd=await _0x32ade5[_0x1a7a8a(0x265)]();console[_0x1a7a8a(0x205)](_0x1a7a8a(0x208)+_0x4f6a19+_0x1a7a8a(0x193)+_0x32ade5[_0x1a7a8a(0x286)]+'):',_0x1922bd);}return 0x0;}const _0x5ad724=await _0x32ade5[_0x1a7a8a(0x1a8)]();let _0x93c1d4=0x0;if(Array[_0x1a7a8a(0x248)](_0x5ad724))_0x93c1d4=_0x5ad724[_0x1a7a8a(0x264)];else _0x5ad724&&_0x5ad724[_0x1a7a8a(0x272)]&&(_0x93c1d4=_0x5ad724[_0x1a7a8a(0x272)][_0x1a7a8a(0x264)]);return _0x93c1d4;}catch(_0x46639a){return console[_0x1a7a8a(0x18e)](_0x1a7a8a(0x195)+_0x4f6a19+_0x1a7a8a(0x262),_0x46639a),0x0;}}async function purgeStorage(_0x2b01f1=null){const _0x5e4e4d=_0x58d31a;console[_0x5e4e4d(0x232)](_0x5e4e4d(0x1d1));const _0x2a268e=_0x2b01f1||await getCollectionId();if(!_0x2a268e)return console['error'](_0x5e4e4d(0x1bb)),toastr[_0x5e4e4d(0x18e)](_0x5e4e4d(0x26d)),![];console[_0x5e4e4d(0x232)](_0x5e4e4d(0x1b5)+_0x2a268e);const _0x379390={'collectionId':_0x2a268e};console[_0x5e4e4d(0x232)](_0x5e4e4d(0x299),JSON[_0x5e4e4d(0x285)](_0x379390,null,0x2));const _0x465409=await fetch('/api/vector/purge',{'method':_0x5e4e4d(0x196),'headers':context['getRequestHeaders'](),'body':JSON[_0x5e4e4d(0x285)](_0x379390)});console[_0x5e4e4d(0x232)](_0x5e4e4d(0x1d7)+_0x465409['status']);if(!_0x465409['ok']){const _0x4e8412=await _0x465409[_0x5e4e4d(0x265)]();console[_0x5e4e4d(0x18e)](_0x5e4e4d(0x23e),_0x4e8412);}else console[_0x5e4e4d(0x232)](_0x5e4e4d(0x18f));return _0x465409['ok'];}function getMessagesForCondensation(_0x12fc04=null){const _0x3038cd=_0x58d31a;if(!settings['condensation'][_0x3038cd(0x228)])return showNotification(_0x3038cd(0x260),_0x3038cd(0x293)),[];const {layerStart:_0x2f6bd2,layerEnd:_0x2b07dd}=settings[_0x3038cd(0x24f)],_0x23f94a=_0x12fc04||settings['condensation']['messageTypes'],_0x434730=context[_0x3038cd(0x1c7)]['length'],_0x1c73f3=Math[_0x3038cd(0x291)](0x0,_0x2f6bd2-0x1),_0xefe8c5=_0x2b07dd===0x0||_0x2b07dd>_0x434730?_0x434730:Math[_0x3038cd(0x1b8)](_0x434730,_0x2b07dd),_0x30167b=context['chat'][_0x3038cd(0x20c)](_0x1c73f3,_0xefe8c5);return _0x30167b['filter'](_0x49c70b=>{const _0x16f684=_0x3038cd,_0x35da83=_0x49c70b[_0x16f684(0x298)]===!![],_0x3a346f=_0x49c70b['is_user']===![];if(!_0x49c70b[_0x16f684(0x1be)]||!_0x49c70b[_0x16f684(0x1be)][_0x16f684(0x28c)]())return![];return _0x23f94a[_0x16f684(0x26e)]&&_0x35da83||_0x23f94a['ai']&&_0x3a346f;});}async function processCondensation(_0x6313ab,_0x58a3cc=()=>{},_0x159a26=null){const _0x2f38f4=_0x58d31a;if(!_0x6313ab||_0x6313ab[_0x2f38f4(0x264)]===0x0)return{'success':![],'error':'No\x20messages\x20to\x20process.'};try{let _0x251b5d,_0x311bf2;const _0x433547=getCharacterName()||_0x2f38f4(0x249);if(_0x159a26){const _0x29c59b=_0x159a26[_0x2f38f4(0x1a7)]??'?',_0x409d9d=_0x159a26['end']===0x0?'末':_0x159a26[_0x2f38f4(0x186)]??'?';_0x251b5d=_0x433547+':\x20'+_0x29c59b+'楼-'+_0x409d9d+'楼';}else{const _0x791d6d=new Date()[_0x2f38f4(0x1ee)](_0x2f38f4(0x241),{'hour12':![]});_0x251b5d=_0x2f38f4(0x1e5)+_0x791d6d;}const _0x1cb289=Object[_0x2f38f4(0x257)](getLocalKnowledgeBases()),_0x59c472=_0x1cb289[_0x2f38f4(0x230)](_0x54c959=>_0x54c959[_0x2f38f4(0x1f4)]===_0x251b5d);if(_0x59c472)_0x311bf2=_0x59c472['id'],_0x58a3cc('[翰林院-核心]\x20检测到同名知识库\x20\x22'+_0x251b5d+_0x2f38f4(0x19e),_0x2f38f4(0x1c4));else{_0x58a3cc(_0x2f38f4(0x25c)+_0x251b5d+_0x2f38f4(0x1c1),'info');const _0x1a1f76=addKnowledgeBase(_0x251b5d,'chat_history');_0x311bf2=_0x1a1f76['id'];}const _0x11a666=getCharacterStableId(),_0x501776=_0x11a666+'_'+_0x311bf2;_0x58a3cc(_0x2f38f4(0x294)+_0x251b5d+_0x2f38f4(0x1bd)+_0x501776+')',_0x2f38f4(0x27c));const _0x55e7ae=[],_0x581bae=context['chat'];for(const _0x5a16c9 of _0x6313ab){const _0x372902=(_0x5a16c9['mes']||'')[_0x2f38f4(0x237)](/<[^>]*>/g,'')[_0x2f38f4(0x28c)]();if(_0x372902['length']===0x0)continue;let _0x38cc9c;if(_0x5a16c9[_0x2f38f4(0x296)]!==undefined&&_0x5a16c9[_0x2f38f4(0x296)]!==null)_0x38cc9c=_0x5a16c9[_0x2f38f4(0x296)];else{const _0x75c47=_0x581bae[_0x2f38f4(0x274)](_0x3cbc5d=>_0x3cbc5d===_0x5a16c9);_0x38cc9c=_0x75c47!==-0x1?_0x75c47+0x1:-0x1;}const _0x388638=new Date(_0x5a16c9['send_date']),_0x2afbc5=isNaN(_0x388638[_0x2f38f4(0x20f)]())?new Date()['toISOString']():_0x388638[_0x2f38f4(0x280)](),_0xe17f52=splitIntoChunks(_0x372902,_0x2f38f4(0x1dd),{'floor':_0x38cc9c,'is_user':_0x5a16c9[_0x2f38f4(0x298)],'timestamp':_0x2afbc5});_0x55e7ae[_0x2f38f4(0x22a)](..._0xe17f52);}if(_0x55e7ae[_0x2f38f4(0x264)]===0x0)return{'success':!![],'count':0x0};_0x58a3cc(_0x2f38f4(0x184)+_0x6313ab[_0x2f38f4(0x264)]+_0x2f38f4(0x1c2)+_0x55e7ae[_0x2f38f4(0x264)]+_0x2f38f4(0x1e8),_0x2f38f4(0x1c4));const _0x5f45d6=settings[_0x2f38f4(0x219)][_0x2f38f4(0x1e9)]||0x5;let _0x33fd55=0x0;for(let _0x2766ea=0x0;_0x2766ea<_0x55e7ae[_0x2f38f4(0x264)];_0x2766ea+=_0x5f45d6){const _0x229b3f=_0x55e7ae[_0x2f38f4(0x20c)](_0x2766ea,_0x2766ea+_0x5f45d6),_0x434277=_0x229b3f[_0x2f38f4(0x18a)](_0x1e97bc=>_0x1e97bc[_0x2f38f4(0x265)]),_0x5ca940=await getEmbeddings(_0x434277);if(_0x229b3f[_0x2f38f4(0x264)]!==_0x5ca940[_0x2f38f4(0x264)])throw new Error('文本块和向量数量不匹配');const _0x438587=_0x229b3f[_0x2f38f4(0x18a)]((_0x3d9f58,_0x3709e6)=>({..._0x3d9f58,'vector':_0x5ca940[_0x3709e6]}));await insertVectors(_0x438587,null,_0x501776),_0x33fd55+=_0x229b3f[_0x2f38f4(0x264)];}if(_0x159a26){const _0x38e75e=_0x159a26['end']===0x0?context[_0x2f38f4(0x1c7)]['length']:_0x159a26[_0x2f38f4(0x186)],_0x1624d6=getCharacterStableId();!settings['condensationHistory'][_0x1624d6]&&(settings[_0x2f38f4(0x20a)][_0x1624d6]={}),settings[_0x2f38f4(0x20a)][_0x1624d6][_0x501776]={'start':_0x159a26[_0x2f38f4(0x1a7)],'end':_0x38e75e,'timestamp':new Date()['toISOString']()},saveSettings(),_0x58a3cc('[翰林院-核心]\x20已为宝库\x20'+_0x501776+_0x2f38f4(0x288)+_0x159a26[_0x2f38f4(0x1a7)]+'-'+_0x38e75e,'info');}_0x58a3cc('[翰林院-核心]\x20聊天记录凝识完成,成功插入\x20'+_0x33fd55+_0x2f38f4(0x214),_0x2f38f4(0x27c));const _0x45ae17=_0x6313ab[_0x2f38f4(0x18a)](_0x299cf0=>{const _0x2ac38b=_0x2f38f4,_0x4b71b5=_0x581bae[_0x2ac38b(0x274)](_0x424a7a=>_0x424a7a===_0x299cf0),_0x35e87a=_0x4b71b5!==-0x1?_0x4b71b5+0x1:-0x1,_0x1993de=_0x299cf0[_0x2ac38b(0x298)]?'用户':getCharacterName()||'AI';return'['+_0x1993de+'\x20-\x20楼层\x20#'+_0x35e87a+']\x20的消息已成功凝识。';});return{'success':!![],'count':_0x33fd55,'messages':_0x45ae17};}catch(_0x137f0a){return console[_0x2f38f4(0x18e)]('[翰林院-核心]\x20processCondensation\x20失败:',_0x137f0a),_0x58a3cc(_0x2f38f4(0x247)+_0x137f0a['message'],_0x2f38f4(0x18e)),{'success':![],'error':_0x137f0a[_0x2f38f4(0x17c)]};}}async function rerankResults(_0x58e66b,_0x30b6fa,_0x3ee856){const _0x436bf6=_0x58d31a;let _0x5de8f4=_0x58e66b,_0x3f6895=![];if(_0x3ee856[_0x436bf6(0x1f7)][_0x436bf6(0x228)]&&_0x58e66b[_0x436bf6(0x264)]>0x0){console['log']('[翰林院-Rerank]\x20开始外部API重排序...');try{const _0x4735b4=_0x58e66b[_0x436bf6(0x18a)](_0x27254b=>_0x27254b[_0x436bf6(0x265)]),_0x18e43e=await executeRerank(_0x30b6fa,_0x4735b4,_0x3ee856[_0x436bf6(0x1f7)]),_0x125b00=_0x58e66b['map']((_0x533aea,_0x2afe5b)=>({..._0x533aea,'original_index':_0x2afe5b}));_0x5de8f4=_0x125b00['map'](_0x45c143=>{const _0x451db7=_0x436bf6,_0x5449f3=_0x18e43e[_0x451db7(0x250)][_0x451db7(0x230)](_0xc9db83=>_0xc9db83[_0x451db7(0x1f9)]===_0x45c143[_0x451db7(0x211)]),_0x27ec4b=_0x5449f3?_0x5449f3[_0x451db7(0x1dc)]:0x0;return{..._0x45c143,'rerank_score':_0x27ec4b};}),_0x3f6895=!![];}catch(_0x39e614){console['error'](_0x436bf6(0x259),_0x39e614);if(_0x3ee856[_0x436bf6(0x1f7)][_0x436bf6(0x263)])showNotification(_0x436bf6(0x1a5)+_0x39e614[_0x436bf6(0x17c)],'error');_0x5de8f4['forEach'](_0x40252f=>_0x40252f[_0x436bf6(0x284)]=0x0);}}else _0x5de8f4['forEach'](_0x14c6fb=>_0x14c6fb[_0x436bf6(0x284)]=0x0);console['log']('[翰林院-Rerank]\x20开始元数据加权最终排序...');const _0x1b8db9=context[_0x436bf6(0x1c7)][_0x436bf6(0x264)],_0x456e8b=_0x3ee856[_0x436bf6(0x1f7)]['hybrid_alpha'],_0x232b10=_0x5de8f4['map'](_0x2d0371=>{const _0x558802=_0x436bf6;let _0x23baec=0x1;const _0x16c444=_0x2d0371[_0x558802(0x223)]||{};switch(_0x16c444[_0x558802(0x1cd)]){case _0x558802(0x231):_0x23baec*=1.2;break;case'manual':_0x23baec*=1.1;break;case _0x558802(0x1dd):if(_0x16c444[_0x558802(0x296)]&&_0x1b8db9>0x0){const _0x1f6ec8=_0x16c444[_0x558802(0x296)]/_0x1b8db9;_0x23baec*=0x1+_0x1f6ec8;}break;}const _0x271b5d=_0x2d0371[_0x558802(0x284)]*_0x456e8b+(_0x2d0371[_0x558802(0x192)]||0x0)*(0x1-_0x456e8b),_0x2b59d4=_0x271b5d*_0x23baec;return{'text':_0x2d0371['text'],'score':_0x2d0371[_0x558802(0x192)],'rerank_score':_0x2d0371[_0x558802(0x284)],'final_score':_0x2b59d4,'metadata':_0x2d0371['metadata']};});_0x232b10['sort']((_0x30f276,_0x341703)=>(_0x341703[_0x436bf6(0x267)]||0x0)-(_0x30f276[_0x436bf6(0x267)]||0x0)),console[_0x436bf6(0x232)](_0x436bf6(0x202));let _0x4327bd=_0x232b10;return _0x3ee856['rerank']['superSortEnabled']&&(_0x4327bd=superSort(_0x232b10)),{'results':_0x4327bd[_0x436bf6(0x20c)](0x0,_0x3ee856[_0x436bf6(0x1f7)]['top_n']),'reranked':_0x3f6895};}async function rearrangeChat(_0x45c500,_0xf9b68d,_0x241a53,_0x164386){const _0x4d59e1=_0x58d31a,_0x248b6a={'novel':_0x4d59e1(0x201),'chat_history':_0x4d59e1(0x1aa),'lorebook':_0x4d59e1(0x181),'manual':_0x4d59e1(0x215)};Object['values'](_0x248b6a)[_0x4d59e1(0x1a4)](_0x5bd74e=>setExtensionPrompt(_0x5bd74e,'',0x0,0x0,![],0x0));if(_0x164386===_0x4d59e1(0x1fa)||!settings[_0x4d59e1(0x219)]['enabled'])return;const _0x581fc3=_0x45c500[_0x4d59e1(0x20c)](-settings[_0x4d59e1(0x22c)][_0x4d59e1(0x282)]);if(_0x581fc3['length']===0x0)return;const _0x4d242c=_0x581fc3[_0x4d59e1(0x18a)](_0x26a0f4=>_0x26a0f4['mes'])['join']('\x20')['replace'](/<[^>]*>/g,'')[_0x4d59e1(0x28c)]();if(!_0x4d242c)return;try{const _0x2fabc2=0x2,_0x5006dd=settings[_0x4d59e1(0x275)]||0x1;let _0x4fd481=![];if(_0x5006dd<_0x2fabc2){console[_0x4d59e1(0x232)](_0x4d59e1(0x1de)+_0x5006dd+'),开始强制重分类所有知识库...'),toastr[_0x4d59e1(0x1c4)](_0x4d59e1(0x18b),_0x4d59e1(0x27a));const _0xd5363c=getKnowledgeBases();for(const _0x2e1271 of Object[_0x4d59e1(0x257)](_0xd5363c)){const _0x5d4d7e=_0x2e1271[_0x4d59e1(0x1f4)],_0x238567=_0x2e1271[_0x4d59e1(0x1cd)];if(_0x5d4d7e[_0x4d59e1(0x1f8)](_0x4d59e1(0x1ac)))_0x2e1271[_0x4d59e1(0x1cd)]=_0x4d59e1(0x242);else{if(_0x5d4d7e[_0x4d59e1(0x1f8)](_0x4d59e1(0x290)))_0x2e1271[_0x4d59e1(0x1cd)]=_0x4d59e1(0x1d9);else _0x5d4d7e[_0x4d59e1(0x28f)]('楼-')&&_0x5d4d7e[_0x4d59e1(0x28f)]('楼')&&_0x5d4d7e[_0x4d59e1(0x28f)](':')?_0x2e1271['source']=_0x4d59e1(0x1dd):_0x2e1271[_0x4d59e1(0x1cd)]=_0x4d59e1(0x231);}_0x238567!==_0x2e1271['source']&&console[_0x4d59e1(0x232)](_0x4d59e1(0x28b)+_0x5d4d7e+_0x4d59e1(0x24c)+(_0x238567||'无')+_0x4d59e1(0x27e)+_0x2e1271['source']+']');}settings['settingsVersion']=_0x2fabc2,_0x4fd481=!![];}_0x4fd481&&(console['log']('[翰林院-户口普查]\x20普查完成,正在保存更新后的户籍...'),saveSettings());let _0x4aa626=[];const _0x4bef35=settings['rerank'][_0x4d59e1(0x25d)];if(_0x4bef35[_0x4d59e1(0x228)]){console[_0x4d59e1(0x232)](_0x4d59e1(0x1df));const _0x25026a=Object[_0x4d59e1(0x257)](getKnowledgeBases())[_0x4d59e1(0x1cf)](_0x854ff7=>_0x854ff7[_0x4d59e1(0x228)]),_0xdfac65=Object[_0x4d59e1(0x1a1)](_0x4bef35['sources'])[_0x4d59e1(0x1cf)](_0x575633=>_0x4bef35[_0x4d59e1(0x1f3)][_0x575633]&&_0x4bef35[_0x4d59e1(0x1f3)][_0x575633]['enabled']),_0x1e1416=[];let _0xc07318=[..._0x25026a];for(const _0x13b55f of _0xdfac65){const _0x45e21b=_0x4bef35['sources'][_0x13b55f],_0x505b8e=_0xc07318[_0x4d59e1(0x1cf)](_0x2bb751=>_0x2bb751[_0x4d59e1(0x1cd)]===_0x13b55f);_0xc07318=_0xc07318[_0x4d59e1(0x1cf)](_0x2b291b=>!_0x505b8e['includes'](_0x2b291b));if(_0x505b8e[_0x4d59e1(0x264)]>0x0){console[_0x4d59e1(0x232)](_0x4d59e1(0x21e)+_0x13b55f+'\x20('+_0x505b8e[_0x4d59e1(0x264)]+_0x4d59e1(0x222));const _0x3b3449=queryVectors(_0x4d242c,{'includeBases':_0x505b8e})[_0x4d59e1(0x1cb)](_0x1dc450=>{const _0x4c5aee=_0x4d59e1;console[_0x4c5aee(0x232)](_0x4c5aee(0x1ec)+_0x13b55f+'\x20返回\x20'+_0x1dc450['length']+_0x4c5aee(0x297));let _0x53d206=_0x1dc450['filter'](_0x39ff3d=>_0x39ff3d[_0x4c5aee(0x223)]?.['source']===_0x13b55f);return _0x53d206=_0x53d206[_0x4c5aee(0x20c)](0x0,_0x45e21b['count']),console[_0x4c5aee(0x232)](_0x4c5aee(0x1b2)+_0x13b55f+_0x4c5aee(0x255)+_0x53d206[_0x4c5aee(0x264)]+_0x4c5aee(0x297)),settings[_0x4c5aee(0x1f7)][_0x4c5aee(0x200)]&&(_0x53d206=superSort(_0x53d206)),_0x53d206;});_0x1e1416['push'](_0x3b3449);}}const _0x2f9ee9=_0xc07318;if(_0x2f9ee9[_0x4d59e1(0x264)]>0x0){console['log'](_0x4d59e1(0x21c)+_0x2f9ee9[_0x4d59e1(0x264)]+'个库)');const _0x113620=queryVectors(_0x4d242c,{'includeBases':_0x2f9ee9})[_0x4d59e1(0x1cb)](async _0x41dcf5=>{const _0xdb6d46=_0x4d59e1;console[_0xdb6d46(0x232)](_0xdb6d46(0x276)+_0x41dcf5[_0xdb6d46(0x264)]+_0xdb6d46(0x297)),console[_0xdb6d46(0x232)]('[翰林院]\x20开始处理常规池...');const _0x215a98=await rerankResults(_0x41dcf5,_0x4d242c,settings),_0x18e181=_0x215a98[_0xdb6d46(0x250)];return console['log'](_0xdb6d46(0x1ca)+(_0x18e181||[])[_0xdb6d46(0x264)]+_0xdb6d46(0x297)),_0x215a98[_0xdb6d46(0x1b7)]&&settings['rerank'][_0xdb6d46(0x263)]&&showNotification(_0xdb6d46(0x243),_0xdb6d46(0x27c)),_0x18e181;});_0x1e1416[_0x4d59e1(0x22a)](_0x113620);}const _0x176c00=await Promise['all'](_0x1e1416);_0x4aa626=_0x176c00[_0x4d59e1(0x235)]();}else{console['log']('[翰林院]\x20进入传统处理流程...');const _0x2e29c9=await queryVectors(_0x4d242c),_0x14465b=await rerankResults(_0x2e29c9,_0x4d242c,settings);_0x4aa626=_0x14465b['results'],_0x14465b['reranked']&&settings[_0x4d59e1(0x1f7)][_0x4d59e1(0x263)]&&showNotification(_0x4d59e1(0x188),'success');}if(!_0x4aa626||_0x4aa626[_0x4d59e1(0x264)]===0x0){console[_0x4d59e1(0x232)](_0x4d59e1(0x1ae));return;}console['log'](_0x4d59e1(0x268)+_0x4aa626[_0x4d59e1(0x264)]+_0x4d59e1(0x297));const _0x208924={'novel':[],'chat_history':[],'lorebook':[],'manual':[]};_0x4aa626[_0x4d59e1(0x1a4)](_0x2a0be3=>{const _0x167af7=_0x4d59e1,_0x360970=_0x2a0be3[_0x167af7(0x223)]?.[_0x167af7(0x1cd)];_0x360970&&_0x208924[_0x167af7(0x1af)](_0x360970)&&_0x208924[_0x360970][_0x167af7(0x22a)](_0x2a0be3);});for(const _0x354748 in _0x208924){const _0x30aea7=_0x208924[_0x354748];if(_0x30aea7[_0x4d59e1(0x264)]===0x0)continue;const _0x58761d=settings[_0x4d59e1(0x19d)+_0x354748[_0x4d59e1(0x237)](_0x4d59e1(0x1ea),'')];if(!_0x58761d){console[_0x4d59e1(0x205)]('[翰林院]\x20未找到来源\x20\x27'+_0x354748+_0x4d59e1(0x1fe));continue;}const _0x82bdb0=_0x30aea7[_0x4d59e1(0x18a)](_0x184620=>_0x184620[_0x4d59e1(0x265)])['join']('\x0a\x0a'),_0x3ad659='{{'+_0x354748[_0x4d59e1(0x237)]('_history','')+_0x4d59e1(0x218);let _0x429dcd=_0x58761d['template'][_0x4d59e1(0x237)](_0x3ad659,_0x82bdb0);_0x429dcd[_0x4d59e1(0x28c)]()&&(_0x429dcd='%%'+_0x248b6a[_0x354748]+'%%'+_0x429dcd),setExtensionPrompt(_0x248b6a[_0x354748],_0x429dcd,_0x58761d[_0x4d59e1(0x1c5)],_0x58761d[_0x4d59e1(0x1e7)],![],_0x58761d[_0x4d59e1(0x1ed)]),console['log']('[翰林院]\x20已为来源\x20\x27'+_0x354748+_0x4d59e1(0x256)+_0x30aea7['length']+'\x20条内容。');}}catch(_0x160d92){console[_0x4d59e1(0x18e)]('[翰林院]\x20检索或注入时发生错误:',_0x160d92);if(settings[_0x4d59e1(0x219)]['notify'])showNotification(_0x4d59e1(0x1fb)+_0x160d92[_0x4d59e1(0x17c)],_0x4d59e1(0x18e));}}async function moveKnowledgeBase(_0x4df7d9,_0x47d52d){const _0x32baae=_0x58d31a,_0x2700ee=_0x47d52d===_0x32baae(0x224)?_0x32baae(0x1d6):_0x32baae(0x224),_0x312456=getCharacterStableId();if(!_0x312456&&_0x2700ee===_0x32baae(0x1d6)){toastr[_0x32baae(0x18e)](_0x32baae(0x21f));return;}const _0x1c73bf=_0x47d52d==='global'?getGlobalKnowledgeBases():getLocalKnowledgeBases(),_0x73f86a=_0x2700ee===_0x32baae(0x224)?getGlobalKnowledgeBases():getLocalKnowledgeBases(),_0x5a6198=_0x1c73bf[_0x4df7d9];if(!_0x5a6198){const _0x41e453=_0x32baae(0x283)+_0x47d52d+_0x32baae(0x18d)+_0x4df7d9+_0x32baae(0x190);console['error'](_0x32baae(0x1fd)+_0x41e453),toastr[_0x32baae(0x18e)](_0x32baae(0x266));return;}_0x47d52d===_0x32baae(0x1d6)&&_0x2700ee==='global'&&!_0x5a6198['owner']&&(console[_0x32baae(0x232)](_0x32baae(0x24a)+_0x4df7d9+'\x20补充所有者ID:\x20'+_0x312456),_0x5a6198[_0x32baae(0x281)]=_0x312456);delete _0x1c73bf[_0x4df7d9],_0x73f86a[_0x4df7d9]=_0x5a6198,saveSettings();const _0x1fe0d9='知识库【'+_0x5a6198[_0x32baae(0x1f4)]+_0x32baae(0x26a)+(_0x2700ee===_0x32baae(0x224)?'全局':'局部')+'。';console[_0x32baae(0x232)](_0x32baae(0x1fd)+_0x1fe0d9);}async function getAllVectorsFromCollection(_0x5df398){const _0x40b2b8=_0x58d31a,_0x6a88f9='*',_0x54f283={'collectionId':_0x5df398,'searchText':_0x6a88f9,'topK':0x2710,'threshold':0x0,'source':_0x40b2b8(0x207),'embeddings':{}},_0xb12183=(await getEmbeddings([_0x6a88f9]))[0x0];_0x54f283['embeddings']={[_0x6a88f9]:_0xb12183};const _0x5c9147=await fetch('/api/vector/query',{'method':_0x40b2b8(0x196),'headers':context[_0x40b2b8(0x1ab)](),'body':JSON['stringify'](_0x54f283)});if(!_0x5c9147['ok']){if(_0x5c9147[_0x40b2b8(0x286)]===0x194)return console[_0x40b2b8(0x232)](_0x40b2b8(0x25f)+_0x5df398+_0x40b2b8(0x1fc)),[];const _0x435b36=await _0x5c9147[_0x40b2b8(0x265)]();throw new Error(_0x40b2b8(0x1d2)+_0x5df398+_0x40b2b8(0x26c)+_0x435b36);}const _0x5cc50b=await _0x5c9147[_0x40b2b8(0x1a8)]();return _0x5cc50b['metadata']||_0x5cc50b[_0x40b2b8(0x250)]||_0x5cc50b[_0x40b2b8(0x197)]||[];}
+'use strict';const _0x1b9b83=_0x3f8a;(function(_0x54c676,_0x509f83){const _0x22a8a0=_0x3f8a,_0x2f0332=_0x54c676();while(!![]){try{const _0x54e0cf=-parseInt(_0x22a8a0(0x26c))/0x1+parseInt(_0x22a8a0(0x2f6))/0x2*(parseInt(_0x22a8a0(0x21c))/0x3)+-parseInt(_0x22a8a0(0x260))/0x4+parseInt(_0x22a8a0(0x2ec))/0x5*(-parseInt(_0x22a8a0(0x2a2))/0x6)+parseInt(_0x22a8a0(0x304))/0x7+parseInt(_0x22a8a0(0x229))/0x8+parseInt(_0x22a8a0(0x2fb))/0x9*(parseInt(_0x22a8a0(0x270))/0xa);if(_0x54e0cf===_0x509f83)break;else _0x2f0332['push'](_0x2f0332['shift']());}catch(_0x182821){_0x2f0332['push'](_0x2f0332['shift']());}}}(_0x7481,0x2b7c1));import{extension_prompt_roles,setExtensionPrompt}from'/script.js';function _0x7481(){const _0x5057a4=['count','\x20条结果。','[翰林院-核心]\x20成功删除知识库\x20','\x20的知识库。','\x20个块。','tags','keys','[翰林院-核心]\x20ingestTextToHanlinyuan\x20失败:','scope','sourceName','[翰林院-核心]\x20知识库\x20','[翰林院-日志]\x20统一角色卡模式开启...','reduce','\x22\x20已从\x20[','extensionSettings','success','part','[翰林院-户口普查]\x20检测到旧版设置\x20(V','Rerank失败:\x20','[翰林院-日志]\x20统计目标集合ID:\x20','hanlinyuanRagProcessor','[翰林院-修复]\x20最终返回数组样本:','substring','relevance_score','聊天记录\x20#','[来源:\x20','error','add','[翰林院]\x20经过预处理后,最终检索文本为空,注入中止。','[翰林院-日志]\x20清空目标集合ID:\x20','\x20失败,删除操作中止。','metadata','condensation','sources','push','[翰林院-日志]\x20忆识存入API错误:','对话记录大总结','\x20条初步结果。','[来源:\x20聊天记录,\x20楼层:\x20#','priorityRetrieval','[翰林院-户口普查]\x20普查完成,正在保存更新后的户籍...','HANLINYUAN_RAG_NOVEL','翰林院忆识核心已启动\x20(V5.2-集成版),已注册到全局\x20hanlinyuanRagProcessor\x20对象。','tagExtractionEnabled','legacy','手动录入:\x20','删除知识库失败,未能清空后端数据。','[翰林院-分块]\x20未知的来源类型\x20\x27','HANLINYUAN_RAG_LOREBOOK','在源作用域\x20\x27','[翰林院-核心]\x20已为宝库\x20','[翰林院-迁移]\x20旧宝库已清空。','is_user','join','指定知识库','values','rerank_score','[翰林院-核心]\x20文本录入失败:\x20','[翰林院]\x20最终准备注入\x20','[翰林院-核心]\x20文本录入任务被用户中止。','then','score','凝识之权未开启','[翰林院-核心]\x20检测到同名知识库\x20\x22','小说:','_global','hashes','[翰林院-日志]\x20没有启用的新知识库,尝试查询旧版单体宝库...','chat_history','[翰林院-日志]\x20去重后剩余\x20','HANLINYUAN_RAG_CHAT','vectors_rearrangeChat','[翰林院-日志]\x20所有知识库查询完毕,共获得\x20','matchThreshold','当前聊天\x20(','78867VrHMmx','
$1','queryPreprocessing','\x20失败:','original_index','[翰林院-配置]\x20','文本块和向量数量不匹配','independentChatMemoryEnabled','[翰林院-日志]\x20查询白名单已提供,将查询\x20','sousuo','message','[翰林院-核心]\x20聊天记录凝识失败:\x20','hanlinyuan-rag-core','949592mwdSqg','index','\x20个向量条目。','enabled','(已锁定:\x20','AbortError','[翰林院-日志]\x20集合\x20','text','\x27\x20注入\x20','reranked','findIndex','chat','\x22\x20已成功重命名为\x20\x22','zh-CN','\x20列表API时出现问题\x20(状态:\x20','slice','[翰林院-Rerank]\x20元数据加权排序完成。','[翰林院-核心]\x20凝识任务已锁定知识库:\x20','retrieval','\x20不存在,返回空数组。','[翰林院-户口普查]\x20知识库\x20\x22',',\x20向量化录入时间:\x20','isArray','\x20个特定知识库。','owner','string','send_date',',\x20第','世界书','bianzhuan','unknown','用户取消了迁移操作','[翰林院-日志]\x20/api/vector/purge\x20响应状态:\x20','toISOString','lorebook','hybrid_alpha','POST','[翰林院-日志]\x20独立聊天记忆模式开启...','stringify','final_score','toString','find','toLocaleString','\x5c$&','[翰林院-日志]\x20无法获取当前聊天ID,跳过聊天宝库。','[翰林院]\x20创建优先查询组:\x20','[翰林院-日志]\x20清空宝库API错误:','depth','\x20(范围:\x20','正在处理\x20','clearJob','知识库名称不能为空。','log','task_','info','1329952QoRweI','batchSize','position','local','操作已取消。','\x27,使用通用分块逻辑。','第1卷','messageTypes','initialized','[翰林院-迁移]\x20用户确认迁移,正在处理旧宝库:\x20','未知角色','/api/vector/query','118995qZMiKu','startsWith','未知条目','forEach','20QokdaF','[翰林院-日志]\x20获取集合\x20','map','[翰林院]\x20常规池处理完毕,产出\x20','HANLINYUAN_RAG_MANUAL','oldId','[翰林院]\x20最终无可用结果,注入中止。','微言录总结','bookName','知识库【','random','\x20个知识块,准备入库。','[翰林院-核心]\x20清空向量集合\x20','warn','source','range','[翰林院-日志]\x20添加\x20','max','忆识存入API错误\x20','[翰林院-核心]\x20聊天记录凝识完成,成功插入\x20','\x20不存在,计为\x200。','abs','toLowerCase','[翰林院-日志]\x20发送到\x20/api/vector/purge\x20的请求体:','maxResults','宏史卷总结','[翰林院-Rerank]\x20外部Rerank失败,将仅使用内部加权。','min','小说:\x20','[翰林院-日志]\x20开始获取所有知识库的向量总数...','saveSettingsDebounced','condensationHistory','saveProgress','start','\x22\x20创建专属知识库...','[翰林院-日志]\x20查询知识库\x20','key','exclusionRules','[翰林院-日志]\x20开始清空宝库...','rerank','\x27\x20的注入设置,跳过处理。','\x20添加新知识库:\x20','all','tiaomu','floor','getContext','[翰林院-修复]\x20最终返回数组长度:\x20','\x22,将数据合并入库。','replace','match','6PbCqBr','injection_','对话记录小总结','[翰林院-日志]\x20统计集合\x20','object','queryMessageCount','status',']\x20的消息已成功凝识。','[翰林院-迁移]\x20用户取消了迁移操作。','[翰林院]\x20常规组返回\x20','[翰林院-核心]\x20尝试删除一个不存在的知识库:\x20','[翰林院-核心]\x20准备为任务\x20\x22','[翰林院-核心]\x20准备删除知识库\x20','comment','检测到旧版数据,正在进行一次性户口普查...','_history','[翰林院-核心]\x20已将\x20','manual','end','embeddings','[翰林院]\x20优先组\x20','[翰林院-配置]\x20为旧版知识库\x20','_text}}',')\x20的状态已切换为:\x20','\x20个条目。','split','includes','quiet','\x20返回\x20','\x27\x20中未找到ID为\x20','hasOwnProperty','data','[翰林院-预处理]\x20原始检索文本:\x20\x22','[翰林院-日志]\x20未能为知识库\x20','[翰林院-预处理]\x20处理后检索文本:\x20\x22','查询集合\x20','length','getTime','未分类世界书',',\x20第1卷,\x20第1章,\x20第','sort','),开始强制重分类所有知识库...','[翰林院-迁移]\x20集合\x20','[翰林院]\x20开始处理常规池...','notify','vector','无法确定要清空的目标宝库。','正在智能分块...','\x20-\x20楼层\x20#','旧版宝库\x20(Legacy)','\x22\x20已删除。','未能生成查询向量。','filter','\x20条内容。','知识库\x20\x22','newId','global','知识库名称不能为空','knowledgeBases','getRequestHeaders','世界书条目','输入文本为空','[翰林院-Rerank]\x20开始外部API重排序...','\x20(集合ID:\x20','advanced','novel','手动录入','[翰林院]\x20创建常规查询组\x20(',',将清空集合:\x20','[翰林院-日志]\x20所有知识库统计完成,总向量数:\x20','[翰林院-核心]\x20已锁定忆识宝库ID:\x20','json','[翰林院-日志]\x20开始向量查询...\x20(目标:\x20','results','830690EuPakq','[翰林院-日志]\x20无法确定要清空的目标集合ID。','在作用域\x20\x27','[翰林院-核心]\x20processCondensation\x20失败:','[翰林院-核心]\x20已为角色\x20',',\x20条目:\x20','\x20的向量总数:\x20','\x20及其向量数据。','mes','第1章','14vzNSzC','entryName','rearrangeChat','trim','has','1871406lBICTW','重命名失败:未找到知识库条目。','/api/vector/list','\x27的文本分割成\x20','\x20记录凝识范围:\x20','user','superSortEnabled','\x20条消息分解为\x20','/api/vector/purge','540008wlwjQP','webllm','aborted','\x0a','now','name','部分]'];_0x7481=function(){return _0x5057a4;};return _0x7481();}import*as _0x40b50c from'./utils/context-utils.js';import{getCollectionIdInfo,getCharacterId,getCharacterStableId}from'./utils/context-utils.js';import{defaultSettings as _0x584004}from'./rag-settings.js';import{extractBlocksByTags,applyExclusionRules}from'./utils/rag-tag-extractor.js';import*as _0x3ebb05 from'./ingestion-manager.js';import{getEmbeddings,fetchEmbeddingModels as _0x1ca542,fetchRerankModels as _0x2e4363,executeRerank,testApiConnection as _0x5c5f1d}from'./rag-api.js';import{superSort}from'./super-sorter.js';const MODULE_NAME=_0x1b9b83(0x228),OFFICIAL_REARRANGE_CHAT_FUNCTION_NAME=_0x1b9b83(0x218),GLOBAL_SCOPE_ID=_0x1b9b83(0x212);let context=null,settings=null,lockedCollectionId=null;function filterWorldbooks(_0x4b91f9,_0x529a87){const _0xb8bc3a=_0x1b9b83;if(!_0x4b91f9||!_0x4b91f9[_0xb8bc3a(0x2f9)]())return _0x529a87;const _0x343394=_0x4b91f9[_0xb8bc3a(0x286)]()[_0xb8bc3a(0x2f9)]();return _0x529a87['filter'](_0x56f619=>{const _0x166dc0=_0xb8bc3a;return _0x56f619[_0x166dc0(0x286)]()[_0x166dc0(0x2bc)](_0x343394)||containsPinyinMatch(_0x56f619,_0x343394);});}function filterWorldbookEntries(_0x56df26,_0x54996a){const _0x37488f=_0x1b9b83;if(!_0x56df26||!_0x56df26['trim']())return _0x54996a;const _0x1b59bc=_0x56df26[_0x37488f(0x286)]()[_0x37488f(0x2f9)]();return _0x54996a['filter'](_0x126c26=>{const _0x5ad8b3=_0x37488f,_0x48a9a8=[_0x126c26['comment']||'',_0x126c26[_0x5ad8b3(0x294)]||'',_0x126c26['content']||''][_0x5ad8b3(0x206)]('\x20')['toLowerCase']();return _0x48a9a8['includes'](_0x1b59bc)||containsPinyinMatch(_0x126c26[_0x5ad8b3(0x2af)]||'',_0x1b59bc);});}function containsPinyinMatch(_0x28b283,_0x1f8378){const _0x571320=_0x1b9b83,_0x3bf41b={'世界书':'sjshu','条目':_0x571320(0x29b),'编纂':_0x571320(0x246),'搜索':_0x571320(0x225)},_0x46d35e=_0x3bf41b[_0x28b283];return _0x46d35e&&_0x46d35e[_0x571320(0x2bc)](_0x1f8378);}function highlightSearchMatch(_0x125485,_0x27e3df){const _0x205032=_0x1b9b83;if(!_0x27e3df||!_0x27e3df[_0x205032(0x2f9)]())return _0x125485;const _0x170cc0=new RegExp('('+_0x27e3df[_0x205032(0x2a0)](/[.*+?^${}()|[\]\\]/g,_0x205032(0x254))+')','gi');return _0x125485[_0x205032(0x2a0)](_0x170cc0,_0x205032(0x21d));}function _0x3f8a(_0x167646,_0x55d937){const _0x748139=_0x7481();return _0x3f8a=function(_0x3f8aa8,_0x22de2b){_0x3f8aa8=_0x3f8aa8-0x1ed;let _0x51c572=_0x748139[_0x3f8aa8];return _0x51c572;},_0x3f8a(_0x167646,_0x55d937);}function debounce(_0x4a8276,_0x5aef79){let _0x273690;return function _0x5b16fe(..._0x57144d){const _0x510a60=()=>{clearTimeout(_0x273690),_0x4a8276(..._0x57144d);};clearTimeout(_0x273690),_0x273690=setTimeout(_0x510a60,_0x5aef79);};}export{initialize,getSettings,saveSettings,resetSettings,_0x5c5f1d as testApiConnection,_0x1ca542 as fetchEmbeddingModels,_0x2e4363 as fetchRerankModels,getVectorCount,purgeStorage,getMessagesForCondensation,processCondensation,ingestTextToHanlinyuan,getCollectionId,toggleSessionLock,isSessionLocked,getLockedSessionInfo,addKnowledgeBase,removeKnowledgeBase,getLocalKnowledgeBases,getGlobalKnowledgeBases,toggleKnowledgeBase,moveKnowledgeBase,filterWorldbooks,filterWorldbookEntries,highlightSearchMatch,debounce,renameKnowledgeBase};function initialize(){const _0x347410=_0x1b9b83;context=SillyTavern[_0x347410(0x29d)]();if(!context){console[_0x347410(0x325)]('[翰林院]\x20未能获取SillyTavern上下文,初始化失败。');return;}settings=getSettings(),!window['hanlinyuanRagProcessor']&&(window[_0x347410(0x31f)]={}),window['hanlinyuanRagProcessor'][_0x347410(0x2f8)]=rearrangeChat,window[_0x347410(0x31f)][_0x347410(0x268)]=!![],console[_0x347410(0x25d)](_0x347410(0x1fb));}async function ingestTextToHanlinyuan(_0x62fcd6,_0x3b4031=_0x1b9b83(0x2b3),_0x1e7154={},_0x41d20f=()=>{},_0x3a2583=null,_0x5cd49e=()=>{},_0x48b6a4=()=>{},_0x1d4b3c=null,_0x5e4618=0x0){const _0xf0f773=_0x1b9b83;if(!_0x62fcd6||!_0x62fcd6[_0xf0f773(0x2f9)]())return{'success':![],'error':_0xf0f773(0x2df)};if(!settings)return{'success':![],'error':'核心未初始化'};try{const _0x4439a2=getCollectionIdInfo(),_0x4402c0=await _0x33e1dc();if(_0x4439a2[_0xf0f773(0x275)]&&_0x4439a2['oldId']===_0x4402c0&&_0x4439a2['oldId']!==_0x4439a2[_0xf0f773(0x2d9)]){const _0x16523d=confirm('检测到旧版数据。此操作将把旧数据迁移到新格式,过程不可逆,是否继续?');if(_0x16523d)_0x5cd49e(_0xf0f773(0x269)+_0x4439a2[_0xf0f773(0x275)],_0xf0f773(0x27d)),await purgeStorage(_0x4439a2[_0xf0f773(0x275)]),_0x5cd49e(_0xf0f773(0x204),_0xf0f773(0x31a));else return _0x5cd49e(_0xf0f773(0x2aa),_0xf0f773(0x25f)),toastr['info'](_0xf0f773(0x264)),{'success':![],'error':_0xf0f773(0x248)};}let _0x116e64,_0x2bcb2c;const _0x5b1854=new Date()[_0xf0f773(0x253)](_0xf0f773(0x236),{'hour12':![]}),_0xe4837=getCharacterName()||_0xf0f773(0x26a);switch(_0x3b4031){case _0xf0f773(0x215):const _0x4e597e=_0x1e7154[_0xf0f773(0x27f)]||{},_0x1972be=_0x4e597e['start']??'?',_0x588227=_0x4e597e[_0xf0f773(0x2b4)]===0x0?'末':_0x4e597e['end']??'?';_0x116e64=_0xe4837+':\x20'+_0x1972be+'楼-'+_0x588227+'楼';break;case _0xf0f773(0x24b):const _0x1a41bc=_0x1e7154['bookName']||_0xf0f773(0x2c8);if(_0x1e7154[_0xf0f773(0x2f7)]&&_0x1e7154[_0xf0f773(0x2f7)][_0xf0f773(0x2bc)](_0xf0f773(0x277)))_0x1e7154[_0xf0f773(0x2f7)]=_0xf0f773(0x2a4);else _0x1e7154[_0xf0f773(0x2f7)]&&_0x1e7154[_0xf0f773(0x2f7)]['includes'](_0xf0f773(0x289))&&(_0x1e7154[_0xf0f773(0x2f7)]=_0xf0f773(0x1f5));const _0x1c17aa=_0x1e7154[_0xf0f773(0x2f7)]||_0xf0f773(0x26e);_0x116e64=_0x1a41bc+':\x20'+_0x1c17aa;break;case _0xf0f773(0x2e3):_0x116e64=_0xf0f773(0x28c)+(_0x1e7154[_0xf0f773(0x314)]||'未知小说');break;case _0xf0f773(0x2b3):default:_0x116e64='手动录入:\x20'+_0x5b1854;break;}const _0x1e0f95=Object[_0xf0f773(0x208)](getKnowledgeBases()),_0x37232c=_0x1e0f95[_0xf0f773(0x252)](_0x4018e9=>_0x4018e9[_0xf0f773(0x309)]===_0x116e64);if(_0x37232c)_0x2bcb2c=_0x37232c['id'],_0x5cd49e(_0xf0f773(0x210)+_0x116e64+_0xf0f773(0x29f),_0xf0f773(0x25f));else{_0x5cd49e(_0xf0f773(0x2ad)+_0x116e64+'\x22\x20创建专属知识库...',_0xf0f773(0x25f));const _0x517b9d=addKnowledgeBase(_0x116e64,_0x3b4031);_0x2bcb2c=_0x517b9d['id'];}const _0x3239e7=getCharacterStableId(),_0x3f76e0=_0x3239e7+'_'+_0x2bcb2c;_0x5cd49e('[翰林院-核心]\x20已创建并锁定知识库:\x20'+_0x116e64+_0xf0f773(0x2e1)+_0x3f76e0+')',_0xf0f773(0x31a)),_0x5cd49e(_0xf0f773(0x2e8)+_0x3f76e0,'info'),_0x41d20f({'message':_0xf0f773(0x2d1),'processed':0x0,'total':0x1});const _0x1ddc72=splitIntoChunks(_0x62fcd6,_0x3b4031,_0x1e7154),_0x4ced4a=_0x1ddc72['length'];if(_0x3a2583?.[_0xf0f773(0x306)])throw new Error('AbortError');_0x5cd49e('[翰林院-核心]\x20将来源\x27'+_0x116e64+_0xf0f773(0x2fe)+_0x4ced4a+_0xf0f773(0x30f),_0xf0f773(0x25f));if(_0x4ced4a===0x0)return{'success':!![],'count':0x0};const _0x3db141=settings[_0xf0f773(0x23b)][_0xf0f773(0x261)]||0x5;let _0x6715e1=_0x5e4618;for(let _0x421a26=_0x5e4618;_0x421a26<_0x4ced4a;_0x421a26+=_0x3db141){if(_0x3a2583?.[_0xf0f773(0x306)])throw new Error(_0xf0f773(0x22e));const _0x4f13ef=_0x1ddc72[_0xf0f773(0x238)](_0x421a26,_0x421a26+_0x3db141);_0x41d20f({'message':_0xf0f773(0x25a)+(_0x421a26+0x1)+'-'+(_0x421a26+_0x4f13ef['length'])+'\x20块','processed':_0x421a26,'total':_0x4ced4a});const _0x2d1bbe=_0x4f13ef[_0xf0f773(0x272)](_0x42c875=>_0x42c875[_0xf0f773(0x230)]),_0x4c8123=await getEmbeddings(_0x2d1bbe,_0x3a2583);if(_0x3a2583?.[_0xf0f773(0x306)])throw new Error('AbortError');if(_0x4f13ef[_0xf0f773(0x2c6)]!==_0x4c8123['length'])throw new Error(_0xf0f773(0x222));const _0x3d3d10=_0x4f13ef[_0xf0f773(0x272)]((_0x2e1067,_0x2f2213)=>({..._0x2e1067,'vector':_0x4c8123[_0x2f2213]}));await insertVectors(_0x3d3d10,_0x3a2583,_0x3f76e0),_0x6715e1+=_0x4f13ef['length'],_0x1d4b3c&&_0x3ebb05[_0xf0f773(0x290)](_0x1d4b3c,_0x6715e1,_0x4ced4a),await _0x48b6a4();}return _0x1d4b3c&&_0x3ebb05[_0xf0f773(0x25b)](_0x1d4b3c),_0x5cd49e('[翰林院-核心]\x20成功插入\x20'+_0x6715e1+_0xf0f773(0x22b),_0xf0f773(0x31a)),{'success':!![],'count':_0x6715e1};}catch(_0x3ca1ff){if(_0x3ca1ff[_0xf0f773(0x309)]===_0xf0f773(0x22e)){_0x5cd49e(_0xf0f773(0x20c),_0xf0f773(0x27d));throw _0x3ca1ff;}return console[_0xf0f773(0x325)](_0xf0f773(0x312),_0x3ca1ff),_0x5cd49e(_0xf0f773(0x20a)+_0x3ca1ff[_0xf0f773(0x226)],'error'),{'success':![],'error':_0x3ca1ff[_0xf0f773(0x226)]};}}function getSettings(){const _0x3257dc=_0x1b9b83;if(!context||!context['extensionSettings'])return structuredClone(_0x584004);let _0x2424b7=context[_0x3257dc(0x319)][MODULE_NAME];!_0x2424b7&&(_0x2424b7={},context[_0x3257dc(0x319)][MODULE_NAME]=_0x2424b7);_0x2424b7[_0x3257dc(0x28f)]===undefined&&(_0x2424b7['condensationHistory']={});_0x2424b7['knowledgeBases']===undefined&&(_0x2424b7[_0x3257dc(0x2dc)]={});_0x2424b7[_0x3257dc(0x21e)]===undefined&&(_0x2424b7[_0x3257dc(0x21e)]={'enabled':![],'tagExtractionEnabled':![],'tags':'content,details,摘要','exclusionRules':[]});for(const _0x5503c2 in _0x584004){if(_0x2424b7[_0x5503c2]===undefined)_0x2424b7[_0x5503c2]=structuredClone(_0x584004[_0x5503c2]);else{if(typeof _0x584004[_0x5503c2]===_0x3257dc(0x2a6)&&!Array[_0x3257dc(0x23f)](_0x584004[_0x5503c2])&&_0x584004[_0x5503c2]!==null)for(const _0x54fe2f in _0x584004[_0x5503c2]){_0x2424b7[_0x5503c2][_0x54fe2f]===undefined&&(_0x2424b7[_0x5503c2][_0x54fe2f]=_0x584004[_0x5503c2][_0x54fe2f]);}}}return _0x2424b7;}function saveSettings(){const _0x55f3c4=_0x1b9b83;if(context)context[_0x55f3c4(0x28e)]();}function resetSettings(){const _0x282815=_0x1b9b83;context&&(context[_0x282815(0x319)][MODULE_NAME]=structuredClone(_0x584004),saveSettings());}function showNotification(_0x149bc0,_0x569634='info'){toastr[_0x569634](_0x149bc0);}function getTagForSource(_0x54110d){const _0x5dc775=_0x1b9b83;switch(_0x54110d){case _0x5dc775(0x215):return'聊天记录';case'lorebook':return _0x5dc775(0x245);case'manual':return'手动录入';case _0x5dc775(0x2e3):return'小说录入';default:return'资料';}}function splitIntoChunks(_0x4d87f1,_0x5ac227,_0x94d6cb={}){const _0x5074a8=_0x1b9b83;switch(_0x5ac227){case'novel':return _chunkForNovel(_0x4d87f1,_0x94d6cb);case'chat_history':return _chunkForChatHistory(_0x4d87f1,_0x94d6cb);case'lorebook':return _chunkForLorebook(_0x4d87f1,_0x94d6cb);case'manual':return _chunkForManual(_0x4d87f1,_0x94d6cb);default:console['warn'](_0x5074a8(0x200)+_0x5ac227+_0x5074a8(0x265));return _chunkForManual(_0x4d87f1,{..._0x94d6cb,'sourceName':_0x94d6cb['sourceName']||'未知来源'});}}function _chunkForNovel(_0x344f4e,_0x4d249f){const _0x41b3a0=_0x1b9b83,{chunkSize:_0x357bf1,overlap:_0x59fb01}=settings[_0x41b3a0(0x2e2)],{sourceName:sourceName='小说'}=_0x4d249f,_0x164e6e=[];if(!_0x344f4e||_0x357bf1<=0x0)return _0x164e6e;const _0x27a776=/(第\s*[一二三四五六七八九十百千万零\d]+\s*卷)/gim,_0x19290d=/(第\s*[一二三四五六七八九十百千万零\d]+\s*[章回节部])|^(Chapter\s+\d+)/gim;let _0x4f56d2=0x0;const _0x50a1db=_0x344f4e['split']('\x0a');let _0x2b8aad=_0x41b3a0(0x266),_0x573c15='第1章',_0x444893=[];function _0x54779c(){const _0x4d4dc9=_0x41b3a0;if(_0x444893[_0x4d4dc9(0x2c6)]===0x0)return;const _0x6ec278=_0x444893[_0x4d4dc9(0x206)]('\x0a');let _0x1b34f4=0x0,_0x563d13=0x1;while(_0x1b34f4<_0x6ec278[_0x4d4dc9(0x2c6)]){const _0x39762=Math[_0x4d4dc9(0x28b)](_0x1b34f4+_0x357bf1,_0x6ec278[_0x4d4dc9(0x2c6)]),_0x52c0a6=_0x6ec278[_0x4d4dc9(0x321)](_0x1b34f4,_0x39762);if(_0x52c0a6['trim']()[_0x4d4dc9(0x2c6)]>0x0){const _0x36ebfc={'source':_0x4d4dc9(0x2e3),'sourceName':sourceName,'timestamp':new Date()['toISOString'](),'globalIndex':_0x4f56d2++,'volume':_0x2b8aad,'chapter':_0x573c15,'section':_0x563d13},_0x13e2f9=getTagForSource(_0x4d4dc9(0x2e3)),_0x3967ce=_0x4d4dc9(0x324)+sourceName+',\x20'+_0x2b8aad+',\x20'+_0x573c15+_0x4d4dc9(0x244)+_0x563d13+'节]',_0x23a854='<'+_0x13e2f9+'>\x0a'+_0x3967ce+'\x0a'+_0x52c0a6+_0x4d4dc9(0x307)+_0x13e2f9+'>';_0x164e6e[_0x4d4dc9(0x1f3)]({'text':_0x23a854,'metadata':_0x36ebfc}),_0x563d13++;}_0x1b34f4+=_0x357bf1-_0x59fb01;if(_0x1b34f4>=_0x6ec278[_0x4d4dc9(0x2c6)])break;}_0x444893=[];}for(const _0x525d4f of _0x50a1db){const _0x4eb88d=_0x525d4f['trim']();if(_0x27a776['test'](_0x4eb88d))_0x54779c(),_0x2b8aad=_0x4eb88d,_0x573c15=_0x41b3a0(0x2f5);else _0x19290d['test'](_0x4eb88d)?(_0x54779c(),_0x573c15=_0x4eb88d):_0x444893[_0x41b3a0(0x1f3)](_0x525d4f);}_0x54779c();if(_0x164e6e[_0x41b3a0(0x2c6)]===0x0&&_0x344f4e['length']>0x0){let _0x432d1d=0x0,_0x3d2563=0x1;while(_0x432d1d<_0x344f4e[_0x41b3a0(0x2c6)]){const _0x17c50b=Math[_0x41b3a0(0x28b)](_0x432d1d+_0x357bf1,_0x344f4e['length']),_0x377b68=_0x344f4e[_0x41b3a0(0x321)](_0x432d1d,_0x17c50b),_0x4a85c9={'source':_0x41b3a0(0x2e3),'sourceName':sourceName,'timestamp':new Date()['toISOString'](),'globalIndex':_0x164e6e[_0x41b3a0(0x2c6)],'volume':_0x41b3a0(0x266),'chapter':_0x41b3a0(0x2f5),'section':_0x3d2563},_0x546c6a=getTagForSource('novel'),_0xdaa32d=_0x41b3a0(0x324)+sourceName+_0x41b3a0(0x2c9)+_0x3d2563+'节]',_0x29e46b='<'+_0x546c6a+'>\x0a'+_0xdaa32d+'\x0a'+_0x377b68+_0x41b3a0(0x307)+_0x546c6a+'>';_0x164e6e['push']({'text':_0x29e46b,'metadata':_0x4a85c9}),_0x3d2563++,_0x432d1d+=_0x357bf1-_0x59fb01;}}return _0x164e6e;}function _chunkForChatHistory(_0x11282a,_0x54fbb3){const _0x8bcd40=_0x1b9b83,{chunkSize:_0x216a1d,overlap:_0x1959ea}=settings[_0x8bcd40(0x2e2)],{floor:_0x331238,is_user:_0x13fc72,timestamp:_0x3e925b}=_0x54fbb3,_0x5b8a02=[];if(!_0x11282a||_0x216a1d<=0x0)return _0x5b8a02;let _0x3a6a57=0x1,_0x360422=0x0;while(_0x360422<_0x11282a[_0x8bcd40(0x2c6)]){const _0xfde49f=Math[_0x8bcd40(0x28b)](_0x360422+_0x216a1d,_0x11282a['length']),_0x4a3b2d=_0x11282a['substring'](_0x360422,_0xfde49f),_0x17bf14=_0x8bcd40(0x1f7)+_0x331238+_0x8bcd40(0x244)+_0x3a6a57+_0x8bcd40(0x30a),_0x13e4c2=getTagForSource('chat_history'),_0x41764a='<'+_0x13e4c2+'>\x0a'+_0x17bf14+'\x0a'+_0x4a3b2d+_0x8bcd40(0x307)+_0x13e4c2+'>';_0x5b8a02[_0x8bcd40(0x1f3)]({'text':_0x41764a,'metadata':{'source':_0x8bcd40(0x215),'sourceName':'聊天记录\x20#'+_0x331238,'floor':_0x331238,'part':_0x3a6a57,'is_user':_0x13fc72,'timestamp':_0x3e925b}}),_0x3a6a57++,_0x360422+=_0x216a1d-_0x1959ea;if(_0x360422>=_0x11282a[_0x8bcd40(0x2c6)])break;}return _0x5b8a02;}function _chunkForLorebook(_0x9054de,_0x5b4823){const _0x37195a=_0x1b9b83,{chunkSize:_0x221df0,overlap:_0x3bd45f}=settings['advanced'],{bookName:bookName=_0x37195a(0x245),entryName:entryName=_0x37195a(0x2de)}=_0x5b4823,_0x42c29d=[];if(!_0x9054de||_0x221df0<=0x0)return _0x42c29d;let _0x3ed1cd=0x1,_0x4d7bda=0x0;while(_0x4d7bda<_0x9054de[_0x37195a(0x2c6)]){const _0x518e4e=Math[_0x37195a(0x28b)](_0x4d7bda+_0x221df0,_0x9054de[_0x37195a(0x2c6)]),_0x56e951=_0x9054de[_0x37195a(0x321)](_0x4d7bda,_0x518e4e),_0x49ea92=_0x37195a(0x324)+bookName+_0x37195a(0x2f1)+entryName+_0x37195a(0x244)+_0x3ed1cd+_0x37195a(0x30a),_0x76daec=getTagForSource(_0x37195a(0x24b)),_0x1f1385='<'+_0x76daec+'>\x0a'+_0x49ea92+'\x0a'+_0x56e951+_0x37195a(0x307)+_0x76daec+'>';_0x42c29d['push']({'text':_0x1f1385,'metadata':{'source':'lorebook','sourceName':bookName+':\x20'+entryName,'bookName':bookName,'entryName':entryName,'part':_0x3ed1cd,'timestamp':new Date()[_0x37195a(0x24a)]()}}),_0x3ed1cd++,_0x4d7bda+=_0x221df0-_0x3bd45f;if(_0x4d7bda>=_0x9054de[_0x37195a(0x2c6)])break;}return _0x42c29d;}function _chunkForManual(_0x25f125,_0x597ec6){const _0x12175c=_0x1b9b83,{chunkSize:_0x669ac9,overlap:_0x49e587}=settings[_0x12175c(0x2e2)],{sourceName:sourceName=_0x12175c(0x2e4)}=_0x597ec6,_0x3be22f=[];if(!_0x25f125||_0x669ac9<=0x0)return _0x3be22f;const _0x196110=new Date(),_0x1972b5=_0x196110[_0x12175c(0x253)]('zh-CN');let _0x56a667=0x1,_0x444a8f=0x0;while(_0x444a8f<_0x25f125[_0x12175c(0x2c6)]){const _0x142788=Math[_0x12175c(0x28b)](_0x444a8f+_0x669ac9,_0x25f125[_0x12175c(0x2c6)]),_0x444fc0=_0x25f125[_0x12175c(0x321)](_0x444a8f,_0x142788),_0x18a992=_0x12175c(0x324)+sourceName+_0x12175c(0x23e)+_0x1972b5+_0x12175c(0x244)+_0x56a667+'部分]',_0x4dbbed=getTagForSource(_0x12175c(0x2b3)),_0x469f14='<'+_0x4dbbed+'>\x0a'+_0x18a992+'\x0a'+_0x444fc0+'\x0a'+_0x4dbbed+'>';_0x3be22f[_0x12175c(0x1f3)]({'text':_0x469f14,'metadata':{'source':_0x12175c(0x2b3),'sourceName':sourceName,'part':_0x56a667,'timestamp':_0x196110[_0x12175c(0x24a)]()}}),_0x56a667++,_0x444a8f+=_0x669ac9-_0x49e587;if(_0x444a8f>=_0x25f125[_0x12175c(0x2c6)])break;}return _0x3be22f;}import{getCollectionId as _0x33e1dc,getCharacterName,getChatId}from'./utils/context-utils.js';async function getCollectionId(){const _0x231b92=_0x1b9b83;if(lockedCollectionId)return lockedCollectionId;const _0x43eda9=settings['retrieval'][_0x231b92(0x223)];return _0x43eda9?getChatId():await _0x33e1dc();}async function toggleSessionLock(){return lockedCollectionId?(lockedCollectionId=null,![]):(lockedCollectionId=await _0x33e1dc(),!![]);}function isSessionLocked(){return lockedCollectionId!==null;}function getLockedSessionInfo(){const _0x1bbc96=_0x1b9b83;if(!lockedCollectionId)return null;return{'id':lockedCollectionId,'name':_0x1bbc96(0x22d)+lockedCollectionId[_0x1bbc96(0x321)](0x0,0x8)+'...)'};}function getLocalKnowledgeBases(){const _0x1a3b1e=_0x1b9b83,_0x33dd6c=getCharacterStableId();return!settings['knowledgeBases'][_0x33dd6c]&&(settings[_0x1a3b1e(0x2dc)][_0x33dd6c]={}),settings[_0x1a3b1e(0x2dc)][_0x33dd6c];}function getGlobalKnowledgeBases(){const _0x191758=_0x1b9b83;return!settings[_0x191758(0x2dc)][GLOBAL_SCOPE_ID]&&(settings[_0x191758(0x2dc)][GLOBAL_SCOPE_ID]={}),settings[_0x191758(0x2dc)][GLOBAL_SCOPE_ID];}function getKnowledgeBases(){const _0x596f68=getLocalKnowledgeBases(),_0x2b3b4f=getGlobalKnowledgeBases();return{..._0x2b3b4f,..._0x596f68};}function addKnowledgeBase(_0x496691,_0xcfd421=_0x1b9b83(0x2b3)){const _0x3d5f55=_0x1b9b83;if(!_0x496691||!_0x496691[_0x3d5f55(0x2f9)]())throw new Error(_0x3d5f55(0x2db));const _0x3545f7=getCharacterStableId(),_0x12a384=getLocalKnowledgeBases(),_0x4c135c=_0x3d5f55(0x25e)+Date[_0x3d5f55(0x308)]()+'_'+Math[_0x3d5f55(0x27a)]()[_0x3d5f55(0x251)](0x24)['substring'](0x2,0x9),_0x1ec54d={'id':_0x4c135c,'name':_0x496691[_0x3d5f55(0x2f9)](),'enabled':!![],'createdAt':new Date()[_0x3d5f55(0x24a)](),'owner':_0x3545f7,'source':_0xcfd421};return _0x12a384[_0x4c135c]=_0x1ec54d,saveSettings(),console['log'](_0x3d5f55(0x2f0)+_0x3545f7+_0x3d5f55(0x299)+_0x496691+'\x20(ID:\x20'+_0x4c135c+')'),_0x1ec54d;}async function removeKnowledgeBase(_0x22bf6a,_0x455b51){const _0x562f68=_0x1b9b83,_0x45e7a7=getCharacterStableId(),_0xbe7173=_0x455b51===_0x562f68(0x2da)?getGlobalKnowledgeBases():getLocalKnowledgeBases(),_0xd235f9=_0xbe7173[_0x22bf6a],_0x444f76=_0xd235f9?.[_0x562f68(0x309)]||_0x22bf6a;if(!_0xd235f9){console[_0x562f68(0x27d)](_0x562f68(0x2ac)+_0x22bf6a+_0x562f68(0x259)+_0x455b51+')');return;}const _0x9aee4b=_0x455b51==='global'?_0xd235f9[_0x562f68(0x241)]||GLOBAL_SCOPE_ID:_0x45e7a7,_0xc3242c=_0x9aee4b+'_'+_0x22bf6a;console[_0x562f68(0x25d)](_0x562f68(0x2ae)+_0x22bf6a+_0x562f68(0x2e6)+_0xc3242c);const _0x80e4c4=await purgeStorage(_0xc3242c);_0x80e4c4?(delete _0xbe7173[_0x22bf6a],saveSettings(),console[_0x562f68(0x25d)](_0x562f68(0x30d)+_0x22bf6a+_0x562f68(0x2f3)),toastr[_0x562f68(0x31a)](_0x562f68(0x2d8)+_0x444f76+_0x562f68(0x2d4))):(console['error'](_0x562f68(0x27c)+_0xc3242c+_0x562f68(0x1ef)),toastr[_0x562f68(0x325)](_0x562f68(0x1ff)));}function toggleKnowledgeBase(_0x9b7b71,_0x19c75a){const _0x4dec0d=_0x1b9b83,_0x54a8fd=_0x19c75a===_0x4dec0d(0x2da)?getGlobalKnowledgeBases():getLocalKnowledgeBases();_0x54a8fd[_0x9b7b71]&&(_0x54a8fd[_0x9b7b71]['enabled']=!_0x54a8fd[_0x9b7b71][_0x4dec0d(0x22c)],saveSettings(),console['log'](_0x4dec0d(0x315)+_0x9b7b71+_0x4dec0d(0x259)+_0x19c75a+_0x4dec0d(0x2b9)+(_0x54a8fd[_0x9b7b71]['enabled']?'启用':'禁用')));}function generateHash(_0x51685c){const _0x2f30d2=_0x1b9b83;let _0x4a599b=0x0;for(let _0x149eb4=0x0;_0x149eb4<_0x51685c[_0x2f30d2(0x2c6)];_0x149eb4++){const _0x27762e=_0x51685c['charCodeAt'](_0x149eb4);_0x4a599b=(_0x4a599b<<0x5)-_0x4a599b+_0x27762e,_0x4a599b=_0x4a599b&_0x4a599b;}return Math[_0x2f30d2(0x285)](_0x4a599b)[_0x2f30d2(0x251)](0x24);}async function queryVectors(_0x40c5eb,_0x4ba096={}){const _0x265d5a=_0x1b9b83,{includeBases:includeBases=null}=_0x4ba096;let _0x8c4480=[];console[_0x265d5a(0x25d)](_0x265d5a(0x2ea)+(includeBases?_0x265d5a(0x207):'所有启用库')+')');if(includeBases)_0x8c4480=includeBases,console[_0x265d5a(0x25d)](_0x265d5a(0x224)+_0x8c4480['length']+_0x265d5a(0x240));else{if(settings[_0x265d5a(0x23b)][_0x265d5a(0x223)]){console['log'](_0x265d5a(0x24e));const _0x4f2ad6=getChatId();_0x4f2ad6?(console[_0x265d5a(0x25d)]('[翰林院-日志]\x20添加当前聊天宝库:\x20'+_0x4f2ad6),_0x8c4480['push']({'id':_0x4f2ad6,'name':_0x265d5a(0x21b)+_0x4f2ad6+')','scope':_0x265d5a(0x234)})):console['warn'](_0x265d5a(0x255));const _0x536a26=getGlobalKnowledgeBases(),_0x4f6170=Object[_0x265d5a(0x208)](_0x536a26)[_0x265d5a(0x2d6)](_0x42228c=>_0x42228c[_0x265d5a(0x22c)]);_0x4f6170[_0x265d5a(0x2c6)]>0x0&&(console[_0x265d5a(0x25d)](_0x265d5a(0x280)+_0x4f6170[_0x265d5a(0x2c6)]+'\x20个已启用的全局知识库。'),_0x8c4480[_0x265d5a(0x1f3)](..._0x4f6170[_0x265d5a(0x272)](_0x57042a=>({..._0x57042a,'scope':_0x265d5a(0x2da)}))));}else{console[_0x265d5a(0x25d)](_0x265d5a(0x316));const _0x213a91=getLocalKnowledgeBases(),_0x422147=getGlobalKnowledgeBases(),_0x2e8c1c=Object[_0x265d5a(0x208)](_0x213a91)['filter'](_0x4c3d94=>_0x4c3d94['enabled']),_0x108dd0=Object[_0x265d5a(0x208)](_0x422147)['filter'](_0x2b7bdf=>_0x2b7bdf['enabled']);_0x8c4480[_0x265d5a(0x1f3)](..._0x2e8c1c['map'](_0x2c8217=>({..._0x2c8217,'scope':_0x265d5a(0x263)}))),_0x8c4480[_0x265d5a(0x1f3)](..._0x108dd0['map'](_0x9d9da7=>({..._0x9d9da7,'scope':_0x265d5a(0x2da)})));if(_0x8c4480[_0x265d5a(0x2c6)]===0x0){console['log'](_0x265d5a(0x214));const _0x2ca9aa=await _0x33e1dc();_0x2ca9aa&&_0x8c4480[_0x265d5a(0x1f3)]({'id':null,'name':_0x265d5a(0x2d3),'scope':_0x265d5a(0x1fd)});}}}if(_0x8c4480[_0x265d5a(0x2c6)]===0x0)return console[_0x265d5a(0x25d)]('[翰林院-日志]\x20没有可供查询的知识库,查询中止。'),[];const _0x254933=(await getEmbeddings([_0x40c5eb]))[0x0];if(!_0x254933)throw new Error(_0x265d5a(0x2d5));const _0x290cb7=_0x8c4480[_0x265d5a(0x272)](_0x58bffa=>_executeQueryForBase(_0x58bffa,_0x40c5eb,_0x254933)),_0x232b46=await Promise[_0x265d5a(0x29a)](_0x290cb7);let _0x16be22=_0x232b46['flat']();console[_0x265d5a(0x25d)](_0x265d5a(0x219)+_0x16be22[_0x265d5a(0x2c6)]+_0x265d5a(0x1f6));const _0x2beddf=[],_0x2129a1=new Set();for(const _0x15bfe7 of _0x16be22){if(_0x15bfe7&&typeof _0x15bfe7===_0x265d5a(0x2a6)&&_0x15bfe7['text']&&typeof _0x15bfe7[_0x265d5a(0x230)]===_0x265d5a(0x242)){const _0x59b3bb=_0x15bfe7[_0x265d5a(0x230)]['trim']();_0x59b3bb['length']>0x0&&!_0x2129a1[_0x265d5a(0x2fa)](_0x59b3bb)&&(_0x2129a1[_0x265d5a(0x326)](_0x59b3bb),_0x2beddf[_0x265d5a(0x1f3)](_0x15bfe7));}}console[_0x265d5a(0x25d)](_0x265d5a(0x216)+_0x2beddf[_0x265d5a(0x2c6)]+_0x265d5a(0x30c)),_0x2beddf[_0x265d5a(0x2ca)]((_0x1e6097,_0x238e39)=>(_0x238e39[_0x265d5a(0x20e)]||0x0)-(_0x1e6097[_0x265d5a(0x20e)]||0x0));const _0xf69f8f=[..._0x2beddf];return console[_0x265d5a(0x25d)](_0x265d5a(0x29e)+_0xf69f8f['length']),console[_0x265d5a(0x25d)](_0x265d5a(0x320),JSON['stringify'](_0xf69f8f[_0x265d5a(0x238)](0x0,0x1),null,0x2)),_0xf69f8f;}async function _executeQueryForBase(_0x232d2d,_0x4e0bc4,_0x50c327=null){const _0x9cdbbb=_0x1b9b83,_0x1214c2=getCharacterStableId();let _0xb563f;switch(_0x232d2d[_0x9cdbbb(0x313)]){case _0x9cdbbb(0x1fd):_0xb563f=await _0x33e1dc();break;case'chat':_0xb563f=_0x232d2d['id'];break;case _0x9cdbbb(0x2da):const _0x9f050c=_0x232d2d[_0x9cdbbb(0x241)]||GLOBAL_SCOPE_ID;_0xb563f=_0x9f050c+'_'+_0x232d2d['id'];break;case _0x9cdbbb(0x263):default:_0xb563f=_0x1214c2+'_'+_0x232d2d['id'];break;}if(!_0xb563f)return[];console[_0x9cdbbb(0x25d)]('[翰林院-日志]\x20正在查询知识库:\x20'+_0x232d2d[_0x9cdbbb(0x309)]+'\x20(ID:\x20'+_0xb563f+')');const _0xb01d51=_0x50c327||(await getEmbeddings([_0x4e0bc4]))[0x0];if(!_0xb01d51)return console[_0x9cdbbb(0x325)](_0x9cdbbb(0x2c3)+_0xb563f+'\x20生成查询向量。'),[];const _0x37f99f={'collectionId':_0xb563f,'searchText':_0x4e0bc4,'topK':settings[_0x9cdbbb(0x2e2)][_0x9cdbbb(0x288)],'threshold':settings[_0x9cdbbb(0x2e2)][_0x9cdbbb(0x21a)],'source':_0x9cdbbb(0x305),'embeddings':{[_0x4e0bc4]:_0xb01d51}};try{const _0x17b01d=await fetch(_0x9cdbbb(0x26b),{'method':_0x9cdbbb(0x24d),'headers':context[_0x9cdbbb(0x2dd)](),'body':JSON[_0x9cdbbb(0x24f)](_0x37f99f)});if(!_0x17b01d['ok']){const _0x554835=await _0x17b01d[_0x9cdbbb(0x230)]();return console[_0x9cdbbb(0x325)](_0x9cdbbb(0x293)+_0xb563f+_0x9cdbbb(0x21f),_0x554835),[];}const _0x150c25=await _0x17b01d[_0x9cdbbb(0x2e9)]();let _0x54c265=[];if(Array[_0x9cdbbb(0x23f)](_0x150c25))_0x54c265=_0x150c25;else{if(_0x150c25&&_0x150c25[_0x9cdbbb(0x1f0)]&&Array[_0x9cdbbb(0x23f)](_0x150c25[_0x9cdbbb(0x1f0)]))_0x54c265=_0x150c25[_0x9cdbbb(0x1f0)];else{if(_0x150c25&&_0x150c25['results']&&Array[_0x9cdbbb(0x23f)](_0x150c25['results']))_0x54c265=_0x150c25[_0x9cdbbb(0x2eb)];else _0x150c25&&_0x150c25[_0x9cdbbb(0x2c1)]&&Array[_0x9cdbbb(0x23f)](_0x150c25['data'])&&(_0x54c265=_0x150c25[_0x9cdbbb(0x2c1)]);}}const _0xc3e541=_0x54c265[_0x9cdbbb(0x272)](_0x14e5f9=>{const _0x1533cb=_0x9cdbbb;if(!_0x14e5f9||typeof _0x14e5f9[_0x1533cb(0x230)]!==_0x1533cb(0x242))return null;const _0x20a6aa={'source':_0x1533cb(0x247),'sourceName':'未知'},_0x39938a=_0x14e5f9[_0x1533cb(0x230)][_0x1533cb(0x2a1)](/^<([^>]+)>/),_0x1089a5=_0x39938a?_0x39938a[0x1]:'';switch(_0x1089a5){case'聊天记录':_0x20a6aa[_0x1533cb(0x27e)]=_0x1533cb(0x215);const _0x277b1a=_0x14e5f9[_0x1533cb(0x230)][_0x1533cb(0x2a1)](/楼层:\s*#(\d+),\s*第(\d+)部分/);_0x277b1a&&_0x277b1a[0x1]&&_0x277b1a[0x2]&&(_0x20a6aa[_0x1533cb(0x29c)]=parseInt(_0x277b1a[0x1],0xa),_0x20a6aa[_0x1533cb(0x31b)]=parseInt(_0x277b1a[0x2],0xa),_0x20a6aa[_0x1533cb(0x314)]=_0x1533cb(0x323)+_0x20a6aa[_0x1533cb(0x29c)]);break;case _0x1533cb(0x245):_0x20a6aa[_0x1533cb(0x27e)]='lorebook';const _0xc1eaaa=_0x14e5f9[_0x1533cb(0x230)][_0x1533cb(0x2a1)](/\[来源:\s*([^,]+),\s*条目:\s*([^,]+),\s*第(\d+)部分\]/);_0xc1eaaa&&_0xc1eaaa[0x1]&&_0xc1eaaa[0x2]&&_0xc1eaaa[0x3]&&(_0x20a6aa['bookName']=_0xc1eaaa[0x1][_0x1533cb(0x2f9)](),_0x20a6aa[_0x1533cb(0x2f7)]=_0xc1eaaa[0x2][_0x1533cb(0x2f9)](),_0x20a6aa['part']=parseInt(_0xc1eaaa[0x3],0xa),_0x20a6aa[_0x1533cb(0x314)]=_0x20a6aa[_0x1533cb(0x278)]+':\x20'+_0x20a6aa[_0x1533cb(0x2f7)]);break;case'手动录入':_0x20a6aa[_0x1533cb(0x27e)]=_0x1533cb(0x2b3);const _0x32f2e0=_0x14e5f9[_0x1533cb(0x230)][_0x1533cb(0x2a1)](/\[来源:\s*([^,]+),.*第(\d+)部分\]/);_0x32f2e0&&_0x32f2e0[0x1]&&_0x32f2e0[0x2]&&(_0x20a6aa[_0x1533cb(0x314)]=_0x32f2e0[0x1][_0x1533cb(0x2f9)](),_0x20a6aa['part']=parseInt(_0x32f2e0[0x2],0xa));break;case'小说录入':_0x20a6aa[_0x1533cb(0x27e)]=_0x1533cb(0x2e3);const _0x53ad34=_0x14e5f9[_0x1533cb(0x230)][_0x1533cb(0x2a1)](/\[来源:\s*([^,]+),\s*([^,]+),\s*([^,]+),\s*([^\]]+)\]/);_0x53ad34&&(_0x20a6aa[_0x1533cb(0x314)]=_0x53ad34[0x1][_0x1533cb(0x2f9)](),_0x20a6aa['volume']=_0x53ad34[0x2][_0x1533cb(0x2f9)](),_0x20a6aa['chapter']=_0x53ad34[0x3][_0x1533cb(0x2f9)](),_0x20a6aa['section']=_0x53ad34[0x4][_0x1533cb(0x2f9)]());break;}return{..._0x14e5f9,'score':_0x14e5f9[_0x1533cb(0x20e)]||0x1,'metadata':_0x20a6aa};})['filter'](Boolean);return console['log']('[翰林院-V13\x20修复]\x20重建元数据后,知识库\x20'+_0x232d2d[_0x9cdbbb(0x309)]+_0x9cdbbb(0x2be)+_0xc3e541['length']+_0x9cdbbb(0x30c)),_0xc3e541;}catch(_0x18f69a){return console[_0x9cdbbb(0x325)](_0x9cdbbb(0x293)+_0xb563f+'\x20时发生网络错误:',_0x18f69a),[];}}async function insertVectors(_0x33e906,_0x1429e7=null,_0x42f8b9){const _0x401441=_0x1b9b83;if(!_0x42f8b9)throw new Error('insertVectors\x20必须接收一个有效的\x20collectionId\x20参数。');if(_0x33e906[_0x401441(0x2c6)]===0x0)return{'success':!![],'count':0x0};const _0x317201=_0x33e906[_0x401441(0x272)]((_0x662daa,_0x135d46)=>({'hash':generateHash(_0x662daa[_0x401441(0x230)]+Date['now']()+_0x135d46),'text':_0x662daa[_0x401441(0x230)],'metadata':_0x662daa[_0x401441(0x1f0)]||{'source':_0x401441(0x247),'timestamp':new Date()[_0x401441(0x24a)]()}})),_0xf427a8=_0x317201[_0x401441(0x317)]((_0x1c97f0,_0x12aa67,_0xcd192b)=>{const _0x2e3b93=_0x401441;return _0x1c97f0[_0x12aa67['text']]=_0x33e906[_0xcd192b][_0x2e3b93(0x2cf)],_0x1c97f0;},{}),_0x188314={'collectionId':_0x42f8b9,'items':_0x317201,'source':_0x401441(0x305),'embeddings':_0xf427a8},_0x239b9a=await fetch('/api/vector/insert',{'method':'POST','headers':context[_0x401441(0x2dd)](),'body':JSON[_0x401441(0x24f)](_0x188314),'signal':_0x1429e7});if(!_0x239b9a['ok']){const _0x39eb17=await _0x239b9a[_0x401441(0x230)]();console[_0x401441(0x325)](_0x401441(0x1f4),_0x39eb17);throw new Error(_0x401441(0x282)+_0x239b9a[_0x401441(0x2a8)]+':\x20'+_0x39eb17);}return{'success':!![],'count':_0x317201['length']};}async function getVectorCount(_0x4dfabc=null,_0x5690b5=_0x1b9b83(0x263)){const _0x34acb2=_0x1b9b83,_0x4ff071=getCharacterStableId();if(_0x4dfabc){const _0x46d73f=_0x5690b5===_0x34acb2(0x2da)?getGlobalKnowledgeBases():getLocalKnowledgeBases(),_0x2563a5=_0x46d73f[_0x4dfabc];if(!_0x2563a5)return console[_0x34acb2(0x27d)]('[翰林院-计数]\x20在作用域\x20\x27'+_0x5690b5+_0x34acb2(0x2bf)+_0x4dfabc+_0x34acb2(0x30e)),0x0;const _0x110858=_0x5690b5===_0x34acb2(0x2da)?_0x2563a5[_0x34acb2(0x241)]||GLOBAL_SCOPE_ID:_0x4ff071,_0x5e617a=_0x110858+'_'+_0x4dfabc;return await countVectorsInCollection(_0x5e617a);}else{if(settings['retrieval']['independentChatMemoryEnabled']){const _0x440dc3=getChatId();if(!_0x440dc3)return 0x0;const _0x1fb5ce=await countVectorsInCollection(_0x440dc3);return console[_0x34acb2(0x25d)]('[翰林院-日志]\x20独立聊天记忆模式开启,聊天\x20'+_0x440dc3+_0x34acb2(0x2f2)+_0x1fb5ce),_0x1fb5ce;}console['log'](_0x34acb2(0x28d));const _0x339955=Object[_0x34acb2(0x208)](getLocalKnowledgeBases()),_0xbf88b0=Object[_0x34acb2(0x208)](getGlobalKnowledgeBases()),_0x4c0bc3=[];_0x339955[_0x34acb2(0x26f)](_0x3b7f93=>{const _0x474030=_0x4ff071+'_'+_0x3b7f93['id'];_0x4c0bc3['push'](countVectorsInCollection(_0x474030));}),_0xbf88b0[_0x34acb2(0x26f)](_0x5617fa=>{const _0x718549=_0x34acb2,_0x2b4679=_0x5617fa[_0x718549(0x241)]||GLOBAL_SCOPE_ID,_0x550991=_0x2b4679+'_'+_0x5617fa['id'];_0x4c0bc3[_0x718549(0x1f3)](countVectorsInCollection(_0x550991));});const _0x5b139d=await _0x33e1dc();_0x4c0bc3[_0x34acb2(0x1f3)](countVectorsInCollection(_0x5b139d));const _0x854521=await Promise[_0x34acb2(0x29a)](_0x4c0bc3),_0x22c663=_0x854521[_0x34acb2(0x317)]((_0x374e5f,_0x277cf3)=>_0x374e5f+_0x277cf3,0x0);return console['log'](_0x34acb2(0x2e7)+_0x22c663),_0x22c663;}}async function countVectorsInCollection(_0xdccc8a){const _0x145a60=_0x1b9b83;if(!_0xdccc8a)return 0x0;console[_0x145a60(0x25d)](_0x145a60(0x31e)+_0xdccc8a);const _0xe3060={'collectionId':_0xdccc8a,'source':_0x145a60(0x305),'embeddings':{}};try{const _0x1263b1=await fetch(_0x145a60(0x2fd),{'method':'POST','headers':context['getRequestHeaders'](),'body':JSON[_0x145a60(0x24f)](_0xe3060)});if(!_0x1263b1['ok']){if(_0x1263b1[_0x145a60(0x2a8)]===0x194)console[_0x145a60(0x25d)](_0x145a60(0x22f)+_0xdccc8a+_0x145a60(0x284));else{const _0x24ed21=await _0x1263b1[_0x145a60(0x230)]();console[_0x145a60(0x27d)](_0x145a60(0x271)+_0xdccc8a+_0x145a60(0x237)+_0x1263b1[_0x145a60(0x2a8)]+'):',_0x24ed21);}return 0x0;}const _0x51560a=await _0x1263b1['json']();let _0x2296d0=0x0;if(Array[_0x145a60(0x23f)](_0x51560a))_0x2296d0=_0x51560a[_0x145a60(0x2c6)];else _0x51560a&&_0x51560a[_0x145a60(0x213)]&&(_0x2296d0=_0x51560a[_0x145a60(0x213)][_0x145a60(0x2c6)]);return _0x2296d0;}catch(_0x340a5d){return console['error'](_0x145a60(0x2a5)+_0xdccc8a+'\x20时发生网络错误:',_0x340a5d),0x0;}}async function purgeStorage(_0x51659e=null){const _0x3e2bd4=_0x1b9b83;console[_0x3e2bd4(0x25d)](_0x3e2bd4(0x296));const _0x408f19=_0x51659e||await getCollectionId();if(!_0x408f19)return console[_0x3e2bd4(0x325)](_0x3e2bd4(0x2ed)),toastr['error'](_0x3e2bd4(0x2d0)),![];console['log'](_0x3e2bd4(0x1ee)+_0x408f19);const _0x1cb105={'collectionId':_0x408f19};console[_0x3e2bd4(0x25d)](_0x3e2bd4(0x287),JSON[_0x3e2bd4(0x24f)](_0x1cb105,null,0x2));const _0xf08ba9=await fetch(_0x3e2bd4(0x303),{'method':_0x3e2bd4(0x24d),'headers':context[_0x3e2bd4(0x2dd)](),'body':JSON[_0x3e2bd4(0x24f)](_0x1cb105)});console[_0x3e2bd4(0x25d)](_0x3e2bd4(0x249)+_0xf08ba9[_0x3e2bd4(0x2a8)]);if(!_0xf08ba9['ok']){const _0x443a27=await _0xf08ba9[_0x3e2bd4(0x230)]();console[_0x3e2bd4(0x325)](_0x3e2bd4(0x257),_0x443a27);}else console['log']('[翰林院-日志]\x20清空宝库API调用成功。');return _0xf08ba9['ok'];}function getMessagesForCondensation(_0x389f4c=null){const _0x59b343=_0x1b9b83;if(!settings[_0x59b343(0x1f1)][_0x59b343(0x22c)])return showNotification(_0x59b343(0x20f),'warning'),[];const {layerStart:_0x1946de,layerEnd:_0x2714b0}=settings[_0x59b343(0x1f1)],_0x8a55c5=_0x389f4c||settings[_0x59b343(0x1f1)][_0x59b343(0x267)],_0x29590f=context[_0x59b343(0x234)][_0x59b343(0x2c6)],_0x466711=Math[_0x59b343(0x281)](0x0,_0x1946de-0x1),_0x12cff4=_0x2714b0===0x0||_0x2714b0>_0x29590f?_0x29590f:Math[_0x59b343(0x28b)](_0x29590f,_0x2714b0),_0x39b6fd=context[_0x59b343(0x234)]['slice'](_0x466711,_0x12cff4);return _0x39b6fd[_0x59b343(0x2d6)](_0x2941e6=>{const _0x14ba98=_0x59b343,_0x440a67=_0x2941e6[_0x14ba98(0x205)]===!![],_0xe05d50=_0x2941e6[_0x14ba98(0x205)]===![];if(!_0x2941e6[_0x14ba98(0x2f4)]||!_0x2941e6[_0x14ba98(0x2f4)]['trim']())return![];return _0x8a55c5[_0x14ba98(0x300)]&&_0x440a67||_0x8a55c5['ai']&&_0xe05d50;});}async function processCondensation(_0x1b633d,_0x165b69=()=>{},_0x2348d1=null){const _0x120a47=_0x1b9b83;if(!_0x1b633d||_0x1b633d[_0x120a47(0x2c6)]===0x0)return{'success':![],'error':'No\x20messages\x20to\x20process.'};try{let _0x10224b,_0x27bdc8;const _0x566c96=getCharacterName()||_0x120a47(0x26a);if(_0x2348d1){const _0x1d4b2e=_0x2348d1[_0x120a47(0x291)]??'?',_0x32cc8a=_0x2348d1[_0x120a47(0x2b4)]===0x0?'末':_0x2348d1[_0x120a47(0x2b4)]??'?';_0x10224b=_0x566c96+':\x20'+_0x1d4b2e+'楼-'+_0x32cc8a+'楼';}else{const _0x4669e6=new Date()[_0x120a47(0x253)](_0x120a47(0x236),{'hour12':![]});_0x10224b='聊天记录:\x20'+_0x4669e6;}const _0x4c0422=Object[_0x120a47(0x208)](getLocalKnowledgeBases()),_0x25f204=_0x4c0422['find'](_0x478507=>_0x478507[_0x120a47(0x309)]===_0x10224b);if(_0x25f204)_0x27bdc8=_0x25f204['id'],_0x165b69(_0x120a47(0x210)+_0x10224b+_0x120a47(0x29f),_0x120a47(0x25f));else{_0x165b69(_0x120a47(0x2ad)+_0x10224b+_0x120a47(0x292),'info');const _0x1636ee=addKnowledgeBase(_0x10224b,_0x120a47(0x215));_0x27bdc8=_0x1636ee['id'];}const _0x5221af=getCharacterStableId(),_0x2cab6d=_0x5221af+'_'+_0x27bdc8;_0x165b69(_0x120a47(0x23a)+_0x10224b+_0x120a47(0x2e1)+_0x2cab6d+')',_0x120a47(0x31a));const _0x4760f5=[],_0x458741=context[_0x120a47(0x234)];for(const _0x4d1b7f of _0x1b633d){const _0x2f320a=(_0x4d1b7f['mes']||'')[_0x120a47(0x2a0)](/<[^>]*>/g,'')['trim']();if(_0x2f320a[_0x120a47(0x2c6)]===0x0)continue;let _0x399d4f;if(_0x4d1b7f[_0x120a47(0x29c)]!==undefined&&_0x4d1b7f[_0x120a47(0x29c)]!==null)_0x399d4f=_0x4d1b7f[_0x120a47(0x29c)];else{const _0x119962=_0x458741[_0x120a47(0x233)](_0x15aa0c=>_0x15aa0c===_0x4d1b7f);_0x399d4f=_0x119962!==-0x1?_0x119962+0x1:-0x1;}const _0x253582=new Date(_0x4d1b7f[_0x120a47(0x243)]),_0x5b6f1d=isNaN(_0x253582[_0x120a47(0x2c7)]())?new Date()[_0x120a47(0x24a)]():_0x253582[_0x120a47(0x24a)](),_0xa4d23=splitIntoChunks(_0x2f320a,'chat_history',{'floor':_0x399d4f,'is_user':_0x4d1b7f['is_user'],'timestamp':_0x5b6f1d});_0x4760f5[_0x120a47(0x1f3)](..._0xa4d23);}if(_0x4760f5['length']===0x0)return{'success':!![],'count':0x0};_0x165b69(_0x120a47(0x2b2)+_0x1b633d[_0x120a47(0x2c6)]+_0x120a47(0x302)+_0x4760f5['length']+_0x120a47(0x27b),'info');const _0x58fbcb=settings['retrieval']['batchSize']||0x5;let _0x521703=0x0;for(let _0x5a05aa=0x0;_0x5a05aa<_0x4760f5[_0x120a47(0x2c6)];_0x5a05aa+=_0x58fbcb){const _0x24e072=_0x4760f5[_0x120a47(0x238)](_0x5a05aa,_0x5a05aa+_0x58fbcb),_0xefd61a=_0x24e072[_0x120a47(0x272)](_0x3f267a=>_0x3f267a[_0x120a47(0x230)]),_0x124dd1=await getEmbeddings(_0xefd61a);if(_0x24e072[_0x120a47(0x2c6)]!==_0x124dd1[_0x120a47(0x2c6)])throw new Error(_0x120a47(0x222));const _0x41b532=_0x24e072[_0x120a47(0x272)]((_0x5388c5,_0x2724a4)=>({..._0x5388c5,'vector':_0x124dd1[_0x2724a4]}));await insertVectors(_0x41b532,null,_0x2cab6d),_0x521703+=_0x24e072[_0x120a47(0x2c6)];}if(_0x2348d1){const _0x155d88=_0x2348d1['end']===0x0?context[_0x120a47(0x234)]['length']:_0x2348d1[_0x120a47(0x2b4)],_0x38bd49=getCharacterStableId();!settings['condensationHistory'][_0x38bd49]&&(settings[_0x120a47(0x28f)][_0x38bd49]={}),settings['condensationHistory'][_0x38bd49][_0x2cab6d]={'start':_0x2348d1[_0x120a47(0x291)],'end':_0x155d88,'timestamp':new Date()[_0x120a47(0x24a)]()},saveSettings(),_0x165b69(_0x120a47(0x203)+_0x2cab6d+_0x120a47(0x2ff)+_0x2348d1[_0x120a47(0x291)]+'-'+_0x155d88,'info');}_0x165b69(_0x120a47(0x283)+_0x521703+_0x120a47(0x2ba),_0x120a47(0x31a));const _0x33a90f=_0x1b633d['map'](_0x273e77=>{const _0x41d45c=_0x120a47,_0x460082=_0x458741[_0x41d45c(0x233)](_0x542006=>_0x542006===_0x273e77),_0x5830d0=_0x460082!==-0x1?_0x460082+0x1:-0x1,_0xc8fb9c=_0x273e77[_0x41d45c(0x205)]?'用户':getCharacterName()||'AI';return'['+_0xc8fb9c+_0x41d45c(0x2d2)+_0x5830d0+_0x41d45c(0x2a9);});return{'success':!![],'count':_0x521703,'messages':_0x33a90f};}catch(_0x2326c7){return console[_0x120a47(0x325)](_0x120a47(0x2ef),_0x2326c7),_0x165b69(_0x120a47(0x227)+_0x2326c7[_0x120a47(0x226)],_0x120a47(0x325)),{'success':![],'error':_0x2326c7[_0x120a47(0x226)]};}}function preprocessQueryText(_0x44623b){const _0x2e4fbd=_0x1b9b83;if(!settings[_0x2e4fbd(0x21e)]['enabled'])return _0x44623b;let _0x18927d=_0x44623b;const {tagExtractionEnabled:_0x3c3a4f,tags:_0x4bdf2c,exclusionRules:_0xb22d8d}=settings[_0x2e4fbd(0x21e)];if(_0x3c3a4f&&_0x4bdf2c){const _0x4e35c7=_0x4bdf2c[_0x2e4fbd(0x2bb)](',')[_0x2e4fbd(0x272)](_0x519dd9=>_0x519dd9[_0x2e4fbd(0x2f9)]())[_0x2e4fbd(0x2d6)](Boolean);if(_0x4e35c7[_0x2e4fbd(0x2c6)]>0x0){const _0x4b97d7=extractBlocksByTags(_0x18927d,_0x4e35c7);_0x18927d=_0x4b97d7[_0x2e4fbd(0x206)]('\x0a\x0a');}}_0xb22d8d&&_0xb22d8d['length']>0x0&&(_0x18927d=applyExclusionRules(_0x18927d,_0xb22d8d));const _0x579862=_0x18927d[_0x2e4fbd(0x2f9)]();return _0x44623b!==_0x579862&&(console[_0x2e4fbd(0x25d)](_0x2e4fbd(0x2c2)+_0x44623b+'\x22'),console[_0x2e4fbd(0x25d)](_0x2e4fbd(0x2c4)+_0x579862+'\x22')),_0x579862;}async function rerankResults(_0x231da9,_0x367f85,_0x1c7108){const _0x59bfd7=_0x1b9b83;let _0x505796=_0x231da9,_0x111492=![];if(_0x1c7108['rerank'][_0x59bfd7(0x22c)]&&_0x231da9[_0x59bfd7(0x2c6)]>0x0){console[_0x59bfd7(0x25d)](_0x59bfd7(0x2e0));try{const _0x535a6f=_0x231da9[_0x59bfd7(0x272)](_0x444109=>_0x444109[_0x59bfd7(0x230)]),_0x2ce7f1=await executeRerank(_0x367f85,_0x535a6f,_0x1c7108[_0x59bfd7(0x297)]),_0x227e60=_0x231da9['map']((_0x1995e8,_0x5bb313)=>({..._0x1995e8,'original_index':_0x5bb313}));_0x505796=_0x227e60[_0x59bfd7(0x272)](_0x1cfe51=>{const _0xbb7801=_0x59bfd7,_0x129901=_0x2ce7f1[_0xbb7801(0x2eb)]['find'](_0x1971c7=>_0x1971c7[_0xbb7801(0x22a)]===_0x1cfe51[_0xbb7801(0x220)]),_0x4d850e=_0x129901?_0x129901[_0xbb7801(0x322)]:0x0;return{..._0x1cfe51,'rerank_score':_0x4d850e};}),_0x111492=!![];}catch(_0x538e78){console[_0x59bfd7(0x325)](_0x59bfd7(0x28a),_0x538e78);if(_0x1c7108[_0x59bfd7(0x297)][_0x59bfd7(0x2ce)])showNotification(_0x59bfd7(0x31d)+_0x538e78[_0x59bfd7(0x226)],_0x59bfd7(0x325));_0x505796[_0x59bfd7(0x26f)](_0x1bce65=>_0x1bce65[_0x59bfd7(0x209)]=0x0);}}else _0x505796[_0x59bfd7(0x26f)](_0x450a42=>_0x450a42[_0x59bfd7(0x209)]=0x0);console[_0x59bfd7(0x25d)]('[翰林院-Rerank]\x20开始元数据加权最终排序...');const _0x485d91=context[_0x59bfd7(0x234)]['length'],_0x335e52=_0x1c7108[_0x59bfd7(0x297)][_0x59bfd7(0x24c)],_0x4ed74e=_0x505796[_0x59bfd7(0x272)](_0x27a7ee=>{const _0x492952=_0x59bfd7;let _0x592591=0x1;const _0x22641d=_0x27a7ee[_0x492952(0x1f0)]||{};switch(_0x22641d[_0x492952(0x27e)]){case _0x492952(0x24b):_0x592591*=1.2;break;case'manual':_0x592591*=1.1;break;case _0x492952(0x215):if(_0x22641d['floor']&&_0x485d91>0x0){const _0x84c190=_0x22641d['floor']/_0x485d91;_0x592591*=0x1+_0x84c190;}break;}const _0x469347=_0x27a7ee['rerank_score']*_0x335e52+(_0x27a7ee['score']||0x0)*(0x1-_0x335e52),_0x3180f6=_0x469347*_0x592591;return{'text':_0x27a7ee[_0x492952(0x230)],'score':_0x27a7ee[_0x492952(0x20e)],'rerank_score':_0x27a7ee[_0x492952(0x209)],'final_score':_0x3180f6,'metadata':_0x27a7ee['metadata']};});_0x4ed74e['sort']((_0x41fa53,_0x3682a0)=>(_0x3682a0[_0x59bfd7(0x250)]||0x0)-(_0x41fa53[_0x59bfd7(0x250)]||0x0)),console[_0x59bfd7(0x25d)](_0x59bfd7(0x239));let _0x247b0a=_0x4ed74e;return _0x1c7108['rerank'][_0x59bfd7(0x301)]&&(_0x247b0a=superSort(_0x4ed74e)),{'results':_0x247b0a['slice'](0x0,_0x1c7108[_0x59bfd7(0x297)]['top_n']),'reranked':_0x111492};}async function rearrangeChat(_0xd72adc,_0x84ed7e,_0x2462f3,_0x5f464f){const _0x3aacff=_0x1b9b83,_0x4c083d={'novel':_0x3aacff(0x1fa),'chat_history':_0x3aacff(0x217),'lorebook':_0x3aacff(0x201),'manual':_0x3aacff(0x274)};Object['values'](_0x4c083d)[_0x3aacff(0x26f)](_0x39226d=>setExtensionPrompt(_0x39226d,'',0x0,0x0,![],0x0));if(_0x5f464f===_0x3aacff(0x2bd)||!settings[_0x3aacff(0x23b)][_0x3aacff(0x22c)])return;const _0x333411=_0xd72adc[_0x3aacff(0x238)](-settings[_0x3aacff(0x2e2)][_0x3aacff(0x2a7)]);if(_0x333411['length']===0x0)return;const _0x22ea4d=settings[_0x3aacff(0x21e)];let _0x184067='';const _0x21ce02=[];for(const _0xa491c8 of _0x333411){if(_0xa491c8['is_user']){_0x21ce02[_0x3aacff(0x1f3)](_0xa491c8[_0x3aacff(0x2f4)]);continue;}if(_0x22ea4d['enabled']&&_0x22ea4d[_0x3aacff(0x1fc)]){const _0x2bfb06=(_0x22ea4d[_0x3aacff(0x310)]||'')[_0x3aacff(0x2bb)](',')[_0x3aacff(0x272)](_0x2444e9=>_0x2444e9['trim']())[_0x3aacff(0x2d6)](Boolean);if(_0x2bfb06['length']>0x0){const _0x364986=extractBlocksByTags(_0xa491c8[_0x3aacff(0x2f4)],_0x2bfb06);if(_0x364986['length']>0x0){const _0x29c873=_0x364986[_0x3aacff(0x272)](_0xd1066e=>{const _0x231876=_0x3aacff,_0x3f72cd=_0xd1066e[_0x231876(0x2a1)](/<[^>]+>([\s\S]*?)<\/[^>]+>/);return _0x3f72cd?_0x3f72cd[0x1]['trim']():'';});_0x21ce02[_0x3aacff(0x1f3)](_0x29c873[_0x3aacff(0x2d6)](Boolean)[_0x3aacff(0x206)]('\x0a\x0a'));}}else _0x21ce02[_0x3aacff(0x1f3)](_0xa491c8[_0x3aacff(0x2f4)]);}else _0x21ce02['push'](_0xa491c8[_0x3aacff(0x2f4)]);}_0x184067=_0x21ce02[_0x3aacff(0x2d6)](Boolean)[_0x3aacff(0x206)]('\x0a\x0a');_0x22ea4d[_0x3aacff(0x22c)]&&(_0x184067=applyExclusionRules(_0x184067,_0x22ea4d[_0x3aacff(0x295)]));_0x184067=_0x184067[_0x3aacff(0x2f9)]();if(!_0x184067){console['log'](_0x3aacff(0x1ed));return;}console[_0x3aacff(0x25d)]('[翰林院-预处理]\x20最终用于检索的文本:\x20\x22'+_0x184067+'\x22');try{const _0x1eabe1=0x2,_0x57ae26=settings['settingsVersion']||0x1;let _0x3babf3=![];if(_0x57ae26<_0x1eabe1){console['log'](_0x3aacff(0x31c)+_0x57ae26+_0x3aacff(0x2cb)),toastr[_0x3aacff(0x25f)](_0x3aacff(0x2b0),'翰林院通告');const _0x56c954=getKnowledgeBases();for(const _0x32163b of Object['values'](_0x56c954)){const _0x295d10=_0x32163b['name'],_0x2db2e5=_0x32163b[_0x3aacff(0x27e)];if(_0x295d10[_0x3aacff(0x26d)](_0x3aacff(0x1fe)))_0x32163b[_0x3aacff(0x27e)]=_0x3aacff(0x2b3);else{if(_0x295d10[_0x3aacff(0x26d)](_0x3aacff(0x211)))_0x32163b['source']=_0x3aacff(0x2e3);else _0x295d10[_0x3aacff(0x2bc)]('楼-')&&_0x295d10[_0x3aacff(0x2bc)]('楼')&&_0x295d10[_0x3aacff(0x2bc)](':')?_0x32163b[_0x3aacff(0x27e)]=_0x3aacff(0x215):_0x32163b[_0x3aacff(0x27e)]='lorebook';}_0x2db2e5!==_0x32163b[_0x3aacff(0x27e)]&&console[_0x3aacff(0x25d)](_0x3aacff(0x23d)+_0x295d10+_0x3aacff(0x318)+(_0x2db2e5||'无')+']\x20更正为\x20['+_0x32163b[_0x3aacff(0x27e)]+']');}settings['settingsVersion']=_0x1eabe1,_0x3babf3=!![];}_0x3babf3&&(console['log'](_0x3aacff(0x1f9)),saveSettings());let _0x279c3d=[];const _0x25cb09=settings['rerank'][_0x3aacff(0x1f8)];if(_0x25cb09[_0x3aacff(0x22c)]){console[_0x3aacff(0x25d)]('[翰林院]\x20进入多路并行独立检索流程...');const _0x1d3c73=Object[_0x3aacff(0x208)](getKnowledgeBases())['filter'](_0xc81fb2=>_0xc81fb2['enabled']),_0x360ae3=Object[_0x3aacff(0x311)](_0x25cb09['sources'])[_0x3aacff(0x2d6)](_0x2e015a=>_0x25cb09[_0x3aacff(0x1f2)][_0x2e015a]&&_0x25cb09['sources'][_0x2e015a]['enabled']),_0x278c80=[];let _0x4276cf=[..._0x1d3c73];for(const _0x3c3bba of _0x360ae3){const _0x204ee2=_0x25cb09['sources'][_0x3c3bba],_0x4fc3a4=_0x4276cf['filter'](_0x58c9aa=>_0x58c9aa[_0x3aacff(0x27e)]===_0x3c3bba);_0x4276cf=_0x4276cf[_0x3aacff(0x2d6)](_0x22706b=>!_0x4fc3a4['includes'](_0x22706b));if(_0x4fc3a4[_0x3aacff(0x2c6)]>0x0){console['log'](_0x3aacff(0x256)+_0x3c3bba+'\x20('+_0x4fc3a4['length']+'个库)');const _0x301adf=queryVectors(_0x184067,{'includeBases':_0x4fc3a4})[_0x3aacff(0x20d)](_0x45ff2b=>{const _0x51fe0b=_0x3aacff;console[_0x51fe0b(0x25d)](_0x51fe0b(0x2b6)+_0x3c3bba+_0x51fe0b(0x2be)+_0x45ff2b['length']+_0x51fe0b(0x30c));let _0x107fe0=_0x45ff2b['filter'](_0x207ace=>_0x207ace[_0x51fe0b(0x1f0)]?.[_0x51fe0b(0x27e)]===_0x3c3bba);return _0x107fe0=_0x107fe0[_0x51fe0b(0x238)](0x0,_0x204ee2[_0x51fe0b(0x30b)]),console[_0x51fe0b(0x25d)]('[翰林院]\x20已从\x20'+_0x3c3bba+'\x20池精确提取\x20'+_0x107fe0[_0x51fe0b(0x2c6)]+_0x51fe0b(0x30c)),settings[_0x51fe0b(0x297)]['superSortEnabled']&&(_0x107fe0=superSort(_0x107fe0)),_0x107fe0;});_0x278c80[_0x3aacff(0x1f3)](_0x301adf);}}const _0x1e3a23=_0x4276cf;if(_0x1e3a23['length']>0x0){console[_0x3aacff(0x25d)](_0x3aacff(0x2e5)+_0x1e3a23[_0x3aacff(0x2c6)]+'个库)');const _0x57dc89=queryVectors(_0x184067,{'includeBases':_0x1e3a23})[_0x3aacff(0x20d)](async _0x3c86c7=>{const _0x1539db=_0x3aacff;console[_0x1539db(0x25d)](_0x1539db(0x2ab)+_0x3c86c7[_0x1539db(0x2c6)]+_0x1539db(0x30c)),console['log'](_0x1539db(0x2cd));const _0x2cd62e=await rerankResults(_0x3c86c7,_0x184067,settings),_0x446637=_0x2cd62e[_0x1539db(0x2eb)];return console['log'](_0x1539db(0x273)+(_0x446637||[])[_0x1539db(0x2c6)]+'\x20条结果。'),_0x2cd62e[_0x1539db(0x232)]&&settings[_0x1539db(0x297)]['notify']&&showNotification('统一检索部分的Rerank已完成',_0x1539db(0x31a)),_0x446637;});_0x278c80[_0x3aacff(0x1f3)](_0x57dc89);}const _0x3f9069=await Promise[_0x3aacff(0x29a)](_0x278c80);_0x279c3d=_0x3f9069['flat']();}else{console[_0x3aacff(0x25d)]('[翰林院]\x20进入传统处理流程...');const _0x1c726b=await queryVectors(_0x184067),_0xd08076=await rerankResults(_0x1c726b,_0x184067,settings);_0x279c3d=_0xd08076[_0x3aacff(0x2eb)],_0xd08076[_0x3aacff(0x232)]&&settings[_0x3aacff(0x297)][_0x3aacff(0x2ce)]&&showNotification('外部Rerank完成','success');}if(!_0x279c3d||_0x279c3d[_0x3aacff(0x2c6)]===0x0){console[_0x3aacff(0x25d)](_0x3aacff(0x276));return;}console[_0x3aacff(0x25d)](_0x3aacff(0x20b)+_0x279c3d['length']+'\x20条结果。');const _0x40a447={'novel':[],'chat_history':[],'lorebook':[],'manual':[]};_0x279c3d[_0x3aacff(0x26f)](_0x430a33=>{const _0x30c31f=_0x3aacff,_0x26be00=_0x430a33[_0x30c31f(0x1f0)]?.['source'];_0x26be00&&_0x40a447[_0x30c31f(0x2c0)](_0x26be00)&&_0x40a447[_0x26be00][_0x30c31f(0x1f3)](_0x430a33);});for(const _0x35b1b3 in _0x40a447){const _0x15d3e3=_0x40a447[_0x35b1b3];if(_0x15d3e3['length']===0x0)continue;const _0x3ac963=settings[_0x3aacff(0x2a3)+_0x35b1b3[_0x3aacff(0x2a0)](_0x3aacff(0x2b1),'')];if(!_0x3ac963){console[_0x3aacff(0x27d)]('[翰林院]\x20未找到来源\x20\x27'+_0x35b1b3+_0x3aacff(0x298));continue;}const _0x370363=_0x15d3e3[_0x3aacff(0x272)](_0x57e7fe=>_0x57e7fe[_0x3aacff(0x230)])[_0x3aacff(0x206)]('\x0a\x0a'),_0x406f70='{{'+_0x35b1b3[_0x3aacff(0x2a0)](_0x3aacff(0x2b1),'')+_0x3aacff(0x2b8);let _0x5a9983=_0x3ac963['template']['replace'](_0x406f70,_0x370363);_0x5a9983[_0x3aacff(0x2f9)]()&&(_0x5a9983='%%'+_0x4c083d[_0x35b1b3]+'%%'+_0x5a9983),setExtensionPrompt(_0x4c083d[_0x35b1b3],_0x5a9983,_0x3ac963[_0x3aacff(0x262)],_0x3ac963[_0x3aacff(0x258)],![],_0x3ac963['depth_role']),console[_0x3aacff(0x25d)]('[翰林院]\x20已为来源\x20\x27'+_0x35b1b3+_0x3aacff(0x231)+_0x15d3e3['length']+_0x3aacff(0x2d7));}}catch(_0x54a11a){console[_0x3aacff(0x325)]('[翰林院]\x20检索或注入时发生错误:',_0x54a11a);if(settings[_0x3aacff(0x23b)][_0x3aacff(0x2ce)])showNotification('忆识检索失败:\x20'+_0x54a11a[_0x3aacff(0x226)],_0x3aacff(0x325));}}async function moveKnowledgeBase(_0x4ae700,_0x20e059){const _0x144333=_0x1b9b83,_0x509ba6=_0x20e059===_0x144333(0x2da)?_0x144333(0x263):_0x144333(0x2da),_0xb65599=getCharacterStableId();if(!_0xb65599&&_0x509ba6===_0x144333(0x263)){toastr[_0x144333(0x325)]('移动失败:没有当前角色,无法移入局部知识库。');return;}const _0x546ec7=_0x20e059==='global'?getGlobalKnowledgeBases():getLocalKnowledgeBases(),_0x4d567f=_0x509ba6===_0x144333(0x2da)?getGlobalKnowledgeBases():getLocalKnowledgeBases(),_0x14d839=_0x546ec7[_0x4ae700];if(!_0x14d839){const _0x593564=_0x144333(0x202)+_0x20e059+_0x144333(0x2bf)+_0x4ae700+_0x144333(0x30e);console[_0x144333(0x325)](_0x144333(0x221)+_0x593564),toastr['error']('移动失败:未找到源条目。');return;}_0x20e059==='local'&&_0x509ba6===_0x144333(0x2da)&&!_0x14d839[_0x144333(0x241)]&&(console[_0x144333(0x25d)](_0x144333(0x2b7)+_0x4ae700+'\x20补充所有者ID:\x20'+_0xb65599),_0x14d839[_0x144333(0x241)]=_0xb65599);delete _0x546ec7[_0x4ae700],_0x4d567f[_0x4ae700]=_0x14d839,saveSettings();const _0x53c09d=_0x144333(0x279)+_0x14d839['name']+'】已成功移动到'+(_0x509ba6===_0x144333(0x2da)?'全局':'局部')+'。';console['log'](_0x144333(0x221)+_0x53c09d);}function renameKnowledgeBase(_0x2f229a,_0x418d82,_0x365afb){const _0x41ab9e=_0x1b9b83;if(!_0x418d82||!_0x418d82[_0x41ab9e(0x2f9)]()){toastr[_0x41ab9e(0x325)](_0x41ab9e(0x25c));throw new Error('知识库名称不能为空');}const _0x4a319a=_0x365afb===_0x41ab9e(0x2da)?getGlobalKnowledgeBases():getLocalKnowledgeBases(),_0x3ff675=_0x4a319a[_0x2f229a];if(!_0x3ff675){const _0xd53043=_0x41ab9e(0x2ee)+_0x365afb+_0x41ab9e(0x2bf)+_0x2f229a+_0x41ab9e(0x30e);console['error'](_0x41ab9e(0x221)+_0xd53043),toastr['error'](_0x41ab9e(0x2fc));throw new Error(_0xd53043);}const _0x46acf8=_0x3ff675[_0x41ab9e(0x309)];_0x3ff675[_0x41ab9e(0x309)]=_0x418d82[_0x41ab9e(0x2f9)](),saveSettings();const _0x2b9060=_0x41ab9e(0x2d8)+_0x46acf8+_0x41ab9e(0x235)+_0x3ff675[_0x41ab9e(0x309)]+'\x22。';console[_0x41ab9e(0x25d)](_0x41ab9e(0x221)+_0x2b9060),toastr[_0x41ab9e(0x31a)](_0x2b9060);}async function getAllVectorsFromCollection(_0x38ae0f){const _0x1fb67c=_0x1b9b83,_0x196688='*',_0x4978fc={'collectionId':_0x38ae0f,'searchText':_0x196688,'topK':0x2710,'threshold':0x0,'source':_0x1fb67c(0x305),'embeddings':{}},_0x1383c7=(await getEmbeddings([_0x196688]))[0x0];_0x4978fc[_0x1fb67c(0x2b5)]={[_0x196688]:_0x1383c7};const _0x23ed4e=await fetch(_0x1fb67c(0x26b),{'method':_0x1fb67c(0x24d),'headers':context['getRequestHeaders'](),'body':JSON[_0x1fb67c(0x24f)](_0x4978fc)});if(!_0x23ed4e['ok']){if(_0x23ed4e[_0x1fb67c(0x2a8)]===0x194)return console['log'](_0x1fb67c(0x2cc)+_0x38ae0f+_0x1fb67c(0x23c)),[];const _0x46975e=await _0x23ed4e[_0x1fb67c(0x230)]();throw new Error(_0x1fb67c(0x2c5)+_0x38ae0f+'\x20失败:\x20'+_0x46975e);}const _0x471fc3=await _0x23ed4e[_0x1fb67c(0x2e9)]();return _0x471fc3[_0x1fb67c(0x1f0)]||_0x471fc3[_0x1fb67c(0x2eb)]||_0x471fc3['data']||[];}
diff --git a/core/rag-settings.js b/core/rag-settings.js
index 72aac6f..54e4a5a 100644
--- a/core/rag-settings.js
+++ b/core/rag-settings.js
@@ -10,6 +10,7 @@ export const defaultSettings = {
embeddingModel: 'text-embedding-3-small',
notify: true,
batchSize: 50,
+ independentChatMemoryEnabled: false,
},
advanced: {
chunkSize: 768,
diff --git a/core/table-system/manager.js b/core/table-system/manager.js
index 1548e27..f4e5f00 100644
--- a/core/table-system/manager.js
+++ b/core/table-system/manager.js
@@ -1 +1 @@
-const _0x373225=_0x4c40;(function(_0x45d635,_0x52df80){const _0x2711f3=_0x4c40,_0x4d7555=_0x45d635();while(!![]){try{const _0x479196=-parseInt(_0x2711f3(0x18a))/0x1+parseInt(_0x2711f3(0x103))/0x2*(-parseInt(_0x2711f3(0x1fe))/0x3)+-parseInt(_0x2711f3(0x17b))/0x4+parseInt(_0x2711f3(0x12d))/0x5+-parseInt(_0x2711f3(0x166))/0x6*(parseInt(_0x2711f3(0x122))/0x7)+parseInt(_0x2711f3(0x192))/0x8*(-parseInt(_0x2711f3(0x15a))/0x9)+-parseInt(_0x2711f3(0x1aa))/0xa*(-parseInt(_0x2711f3(0x13d))/0xb);if(_0x479196===_0x52df80)break;else _0x4d7555['push'](_0x4d7555['shift']());}catch(_0x114787){_0x4d7555['push'](_0x4d7555['shift']());}}}(_0x162f,0x7b19f));import{getContext,extension_settings}from'/scripts/extensions.js';import{saveChat,saveSettingsDebounced}from'/script.js';import{log}from'./logger.js';import{fillWithSecondaryApi}from'./secondary-filler.js';import{getChatPiece,saveChatDebounced}from'../../utils/utils.js';import{extensionName}from'../../utils/settings.js';import{DEFAULT_AI_RULE_TEMPLATE,DEFAULT_AI_FLOW_TEMPLATE}from'./settings.js';import{renderTables}from'../../ui/table-bindings.js';import{updateOrInsertTableInChat}from'../../ui/message-table-renderer.js';const TABLE_DATA_KEY=_0x373225(0x13c);let currentTablesState=null,highlightedCells=new Set(),updatedTables=new Set();export function addHighlight(_0xec6508,_0x20f3cf,_0xc55595){const _0x7e5a16=_0x373225,_0x4606da=_0xec6508+'-'+_0x20f3cf+'-'+_0xc55595;highlightedCells[_0x7e5a16(0x189)](_0x4606da);}export function getHighlights(){return highlightedCells;}export function clearHighlights(){const _0x14d4ef=_0x373225;highlightedCells[_0x14d4ef(0x1d3)]>0x0&&(highlightedCells[_0x14d4ef(0x1a1)](),log('已清除所有单元格高亮标记。',_0x14d4ef(0x14e)));}export function getUpdatedTables(){return updatedTables;}export function clearUpdatedTables(){const _0x1713dc=_0x373225;updatedTables[_0x1713dc(0x1d3)]>0x0&&(updatedTables[_0x1713dc(0x1a1)](),log(_0x1713dc(0x1e0),_0x1713dc(0x14e)));}export function setMemoryState(_0x3cb563){currentTablesState=_0x3cb563;}function _0x162f(){const _0xd3f53f=['rowStatuses','删除列失败:在表格\x20','\x20中操作。','isArray','push','warn','【触发条件】只能在
明确表示要移除或废弃某条设定时,才能删除对应行。','size','状态回退失败,已中止操作。','回退并重新填表操作完成。','\x22\x20的表格已存在。','Amily2-','执行AI指令:\x20insertRow(tableIndex=','batch_filler_rule_template','columnWidths','【触发条件】任何时候,如果此表格的行数超过一行,必须删除旧的行,只保留最新、最准确的一行。','tables','【触发条件】当以下任一情况发生时,必须更新此行:\x0a1.\x20时间发生显著跳跃(例如,\x27几小时后\x27、\x27第二天\x27)。\x0a2.\x20角色从一个地点移动到另一个地点。\x0a3.\x20场景中关键角色的出入导致在场人员发生变化。','导入的预设已强制写入最新消息并立即保存。','body','已清除所有表格的更新标记。','amily2-force-ui-reload','object','未找到任何表格数据或全局预设,使用默认模板。','导入成功','无法找到可锚定的消息或保存失败,新表格可能不会被持久化!',']\x20已被成功废黜。','创建失败','every','【说明】:\x0a','\x20条消息加载表格状态...','some','global_table_preset','这是一个新创建的表格。','\x20的列。','\x22\x20已更新内存状态。','getPrototypeOf','createElement','number','无法找到可锚定的消息或保存失败,清空操作可能不会被持久化!','\x20已在边界。','未在AI返回内容中找到有效的\x20\x20指令块。','mes','全局预设已设置!新聊天将默认使用此预设。','below','download','UI操作\x20\x22',']\x20末尾新增一行。',')行,请结合剧情缩减至(',')超出规定(','1866TIdLsG','无法找到可锚定的消息或保存失败,删除操作可能不会被持久化!','导入全局预设失败:\x20',']\x20的顺序已调整。','【核心作用】此表格用于精确追踪故事发生的即时时空背景,确保时间与空间的连续性。它应该始终只包含一行,代表当前的“镜头”位置。\x0a【字段详解】\x0a-\x20日期:\x20格式为\x27YYYY-MM-DD\x27。若日期未知,请根据上下文合理推断或设定一个初始日期,如\x27大夏3年-9月-10日\x27。\x0a-\x20时段:\x20严格遵循规定(凌晨:0-5时;早晨:5-8时;上午:8-11时;中午:11-13时;下午:13-16时;傍晚:16-19时;晚上:19-24时)。\x0a-\x20时间:\x20格式为\x27HH:MM\x27。若时间未知,可根据时段估算,如\x2708:30\x27。\x0a-\x20地点:\x20描述当前场景发生的具体位置,应尽可能精确,例如\x27XX街的咖啡馆\x27而非\x27城里\x27。\x0a-\x20此地角色:\x20列出当前场景中所有在场且参与互动的主要角色,用\x27/\x27分隔。','file','”已更新为“','rule_delete','filter','batch_filler_flow_template','【触发条件】当任务列表超过10行时,优先删除最早的、已经“已完成”且与当前剧情关联度最低的任务。如果存在内容完全重复的任务,应删除。','886Jlohav',',\x20rowIndex=','执行AI指令时发生错误:\x20','AI\x20指令更新了表格\x20[','【当前(','【全局预设导入】\x0a\x0a这将把选定的预设设置为所有新聊天的默认表格。\x0a\x0a此操作将覆盖任何已存在的全局预设,是否确定?','【触发条件】当一个物品被彻底摧毁、消耗完毕或永久失去其特殊意义时,可以删除。','【删除】:\x20','无法创建表格:名称不能为空。','trim','rowIndex,','stringify','聊天记录不足,无法执行回退操作。','导入的预设中缺少指令模板字段,模板将不会被更新。','所有表格的剧情内容已清空。','表格\x20\x22','无法移动列:索引\x20','UI已更新以显示回退后的状态。',')列,字符超出规定(','填表完成','readAsText','\x20行。','重要原因','新列\x201','charLimitRule','\x20行位置插入了新行。','onload','\x20(索引\x20','input','rows',')第(','6889127DtLHLb','全局预设已清除,新聊天将使用默认模板。','正在尝试从第\x20','已成功创建新表格:[','runner','\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20const\x20{\x20insertRow,\x20deleteRow,\x20updateRow\x20}\x20=\x20runner;\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20',')\x20的第\x20','】已开始下载。','accept',')行以下,但切莫完全删除。】','\x20条消息中找到基准表格数据。','1582890nzrWVY','version','AI指令意图更新不存在的行\x20(rowIndex:\x20','length','插入了新列。','【核心作用】专门用于记录主角掌握的各种技能、魔法、被动能力或特殊专长。\x0a【字段详解】\x0a-\x20技能名:\x20技能的正式名称。\x0a-\x20技能效果:\x20清晰、简洁地描述该技能使用时产生的具体效果、消耗和限制条件。','【触发条件】当一个角色被确认永久性死亡(非假死或失踪),且其存在不再对后续剧情有直接影响时,可以删除该行。','onchange','replace','【触发条件】当一个已知技能的效果发生进化、变异或被添加了新的限制/效果时(例如,技能升级),必须更新其“技能效果”描述。','导入的表格数据格式不正确:\x20','全局预设已被清除。','】已成功导出。','AI指令错误:尝试在不存在的表格索引\x20','【触发条件】当一个物品被明确赋予了特殊意义(如被赠予、在关键事件中扮演重要角色)或展示出独特功能时,应为其创建条目。','amily2_tables_data','234817NYVYjj','\x20的表格。','全局预设已成功导入并保存到扩展设置中。','技能名','normal','用户取消了清除全局预设的操作。','【核心作用】此表格记录了来自的、超越故事本身的“元指令”或世界观设定,拥有最高解释权。内容应被严格遵守,禁止AI自行修改。\x0a【字段详解】\x0a-\x20类型:\x20指令的分类,如\x27世界观设定\x27、\x27剧情走向要求\x27、\x27角色行为禁令\x27。\x0a-\x20具体描述:\x20完整、准确地记录提出的具体要求。','表格不存在。','Amily2-Table-Preset-v3.0-separated_templates','split','【核心作用】此表格是角色关系和状态的核心数据库,用于记录所有在故事中出现的重要角色的详细信息。\x0a【字段详解】\x0a-\x20角色名:\x20角色的唯一标识。\x0a-\x20外貌:\x20描述五官、发型、发色、肤色等面部特征。\x0a-\x20身形:\x20描述身高、体型、肌肉状况、特殊身体标记(如伤疤)等。\x0a-\x20衣着:\x20描述角色当前或标志性的穿着,包括服装、配饰等。\x0a-\x20性格:\x20概括角色的核心性格特质,使用1-3个关键词,如\x27勇敢/鲁莽/忠诚\x27。\x0a-\x20身份:\x20角色的社会背景或出身,如\x27贵族后裔\x27、\x27流浪者\x27。\x0a-\x20职业:\x20角色赖以谋生的工作或职责,如\x27佣兵\x27、\x27学者\x27。\x0a-\x20与关系:\x20描述该角色与主角之间的社会或情感关系,如\x27盟友\x27、\x27导师\x27、\x27敌人\x27。\x0a-\x20爱好:\x20角色的兴趣和消遣活动。\x0a-\x20住所:\x20角色的常住地。\x0a-\x20其他重要信息:\x20记录任何不属于以上类别但对角色至关重要的信息,如特殊能力、过去的经历等。','【清除全局预设】\x0a\x0a您确定要清除已设置的全局预设吗?\x0a\x0a清除后,新聊天将恢复使用扩展内置的默认表格模板。','createObjectURL','”已向','...]','constructor','操作已取消。','info','appendChild','无需清除,当前未设置任何全局预设。','重命名失败:表格不存在。','已根据AI的指示成功更新表格!','无法移动表格:索引\x20','pending-deletion','parse','Amily2-Table-Preset-v2.0-clean','执行失败','Amily2-Table-Preset-v2.0-full','\x20行已标记为待删除。','90189WsluXB','\x20行移动到第\x20','type','无法找到可锚定的消息或保存失败,顺序调整可能不会被持久化!','batchFillerFlowTemplate','toString','具体描述',']\x20的列“','状态回退成功,准备重新填表...','文件格式无效或缺少版本号/表格数据。','已成功将回退后的状态保存至最新消息。','【触发条件】如果发现表格中存在两个描述完全相同的重复技能,应删除其中一个。如果记录了非的技能,应立即删除。','6iCjRWE','角色名','物品栏','无法清空:当前表格状态为空。','charLimitRules','target','\x20条表格操作指令...','纯净预设','batchFillerRuleTemplate','rowLimitRule','【触发条件】当以下情况发生时,应添加新行:\x0a1.\x20角色接下一个明确的、有目标的委托或命令。\x0a2.\x20角色们达成一个具体的、需要在未来执行的约定。\x0a3.\x20角色为自己设定一个长期的、关键性的目标。','回退状态保存失败,操作中止。','join','技能效果','click',',\x20data=','当前没有设置全局预设。','columnIndex','success','表格状态已准备写入消息\x20[','时空栏','2298796NEtxPp',']\x20的规则已更新。','limit','完整备份','其他重要信息','aiTemplate','技能栏','加载全局预设失败:\x20','开始时间/结束时间','缺少状态或目标消息,无法保存。','【触发条件】当在故事中首次成功施展或习得一个全新的、表格中未记录的技能时,必须添加。','预设已成功导入并应用。','设定栏','导入预设失败:\x20','add','894610IQtMEn','\x0a\x20\x20\x20\x20\x20\x20\x20\x20','headers','rule_update','【触发条件】当一个有名有姓的角色首次出现,并与或当前剧情发生有意义的互动时,必须为其创建新的一行。','任务栏','aiFlowTemplate','error','296PVxRgA','成功删除了表格\x20','插入行失败:找不到索引为\x20','fill','message',']\x20的第\x20','rule_add','note','重新填表失败:\x20','操作完成','indexOf','confirm','无法导出:当前表格状态为空。','重命名失败','aiRuleTemplate','clear','【触发条件】只能在明确表示要修改某条设定时,才能更新对应行的描述。','href','回退重填过程中发生错误:\x20','splice','名为\x20\x22','result','removeChild','【触发条件】当通过括号、旁白或其他明确的“第四面墙”方式,提出关于故事背景、规则或未来走向的指令时,必须记录于此。','1540XRKBSe','【触发条件】当角色的任何信息发生持久性或关键性变化时,必须更新对应单元格。例如:\x0a1.\x20外貌/身形/衣着发生永久性改变(如断肢、换上新装备)。\x0a2.\x20性格因重大事件而扭转。\x0a3.\x20身份或职业发生变更(如继承王位、被解雇)。\x0a4.\x20与的关系发生根本性转变(如从敌人变为盟友)。','新列\x20','injectionFlowTemplate','物品名','forEach',')行(','执行AI指令:\x20deleteRow(tableIndex=','files','amily2_ai_template','.json','AI返回内容为空,无法更新表格。','left','表格\x20[','操作成功','extra','revokeObjectURL','从预设模板生成默认表格...','【触发条件】当故事开始,且此表格为空时,必须立即根据初始场景创建第一行。','【增加】:\x20','准备执行从AI返回的\x20','无法回退:聊天记录不足。','name','废黜表格后的状态已强制写入最新消息并立即保存。','\x0a*\x20','导入失败:','AI指令块为空,无需执行任何操作。','map','无法创建表格:名为\x20\x22','【警告】\x0a\x0a导入操作将完全覆盖您当前的AI指令模板和所有表格(包括结构和内容)。\x0a\x0a此操作不可逆,是否确定要继续?',']\x20的表头“','chat',')字限制,请进行缩减。】','正在执行回退并重新填表...'];_0x162f=function(){return _0xd3f53f;};return _0x162f();}export function getMemoryState(){return currentTablesState;}const defaultTemplate={'tables':[{'name':_0x373225(0x17a),'headers':['日期','时段','时间','地点','此地角色'],'note':_0x373225(0x202),'rule_add':_0x373225(0x1bc),'rule_delete':_0x373225(0x1db),'rule_update':_0x373225(0x1dd),'charLimitRules':{},'rowLimitRule':0x1,'rows':[]},{'name':'角色栏','headers':[_0x373225(0x167),'外貌','身形','衣着','性格','身份','职业','与关系','爱好','住所',_0x373225(0x17f)],'note':_0x373225(0x147),'rule_add':_0x373225(0x18e),'rule_delete':_0x373225(0x133),'rule_update':_0x373225(0x1ab),'charLimitRules':{'10':0x1e},'rowLimitRule':0x0,'rows':[]},{'name':_0x373225(0x18f),'headers':['任务名','类型','详情','状态','执行者','地点',_0x373225(0x183),'结果'],'note':'【核心作用】追踪故事中的主要情节线、目标和挑战。只记录对剧情发展有重大影响的“任务”,忽略日常琐事。\x0a【字段详解】\x0a-\x20任务名:\x20任务的简洁概括,如\x27寻找失落的神器\x27。\x0a-\x20类型:\x20任务的分类,如\x27主线\x27、\x27支线\x27、\x27个人\x27、\x27约定\x27。\x0a-\x20详情:\x20对任务目标和背景的简要描述。\x0a-\x20状态:\x20任务的当前进展,如\x27未开始\x27、\x27进行中\x27、\x27已完成\x27、\x27已失败\x27、\x27已取消\x27。\x0a-\x20执行者:\x20负责完成此任务的角色名。\x0a-\x20地点:\x20任务关键环节发生的地点。\x0a-\x20开始时间/结束时间:\x20记录任务的起止时间,格式\x27YYYY-MM-DD\x27,若未结束则结束时间留空。\x0a-\x20结果:\x20任务完成或失败后的最终结果。','rule_add':_0x373225(0x170),'rule_delete':_0x373225(0x102),'rule_update':'【触发条件】当任务的“状态”发生任何变化时,必须更新。例如,从\x27进行中\x27变为\x27已完成\x27。当任务的“详情”或“结果”有新的关键信息补充时,也应更新。','charLimitRules':{},'rowLimitRule':0xa,'rows':[]},{'name':_0x373225(0x168),'headers':[_0x373225(0x1ae),'类型','详情','状态','拥有者',_0x373225(0x119)],'note':'【核心作用】记录那些在故事中具有特殊功能、背景或情感价值的关键物品。普通物品不应记录。\x0a【字段详解】\x0a-\x20物品名:\x20物品的名称。\x0a-\x20类型:\x20物品的分类,如\x27武器\x27、\x27道具\x27、\x27信物\x27、\x27关键物品\x27。\x0a-\x20详情:\x20描述物品的外观、材质和已知功能。\x0a-\x20状态:\x20物品的当前状况,如\x27完好\x27、\x27破损\x27、\x27能量耗尽\x27。\x0a-\x20拥有者:\x20当前持有该物品的角色名。\x0a-\x20重要原因:\x20解释该物品为何重要,例如\x27是解开谜题的钥匙\x27或\x27是母亲的遗物\x27。','rule_add':_0x373225(0x13b),'rule_delete':_0x373225(0x109),'rule_update':'【触发条件】当物品的“状态”(如被损坏)、“拥有者”(如被转交或被盗)或“详情”(如发现了新功能)发生变化时,必须更新。','charLimitRules':{},'rowLimitRule':0x0,'rows':[]},{'name':_0x373225(0x181),'headers':[_0x373225(0x140),_0x373225(0x173)],'note':_0x373225(0x132),'rule_add':_0x373225(0x185),'rule_delete':_0x373225(0x165),'rule_update':_0x373225(0x136),'charLimitRules':{},'rowLimitRule':0x0,'rows':[]},{'name':_0x373225(0x187),'headers':['类型',_0x373225(0x160)],'note':_0x373225(0x143),'rule_add':_0x373225(0x1a9),'rule_delete':_0x373225(0x1d2),'rule_update':_0x373225(0x1a2),'charLimitRules':{},'rowLimitRule':0x0,'rows':[]}]};function getDefaultTables(){const _0x4a6b89=_0x373225;log(_0x4a6b89(0x1bb),_0x4a6b89(0x14e));const _0x936259=JSON[_0x4a6b89(0x155)](JSON[_0x4a6b89(0x10e)](defaultTemplate[_0x4a6b89(0x1dc)]));return _0x936259['forEach'](_0x105556=>{const _0x441803=_0x4a6b89;_0x105556[_0x441803(0x11b)]={'columnIndex':-0x1,'limit':0x0},_0x105556[_0x441803(0x16f)]=0x0,_0x105556[_0x441803(0x1da)]=[];}),_0x936259;}export function loadTables(_0x2d26d5=-0x1){const _0x17ad1c=_0x373225,_0xde1ec3=getContext();if(_0xde1ec3&&_0xde1ec3[_0x17ad1c(0x1c9)]&&_0xde1ec3[_0x17ad1c(0x1c9)][_0x17ad1c(0x130)]>0x0){const _0xc61b3f=_0x2d26d5===-0x1?_0xde1ec3['chat'][_0x17ad1c(0x130)]-0x1:_0x2d26d5-0x1;for(let _0x3d537d=_0xc61b3f;_0x3d537d>=0x0;_0x3d537d--){const _0x5a35bf=_0xde1ec3[_0x17ad1c(0x1c9)][_0x3d537d];if(_0x5a35bf[_0x17ad1c(0x1b9)]&&_0x5a35bf[_0x17ad1c(0x1b9)][TABLE_DATA_KEY]){log('在第\x20'+_0x3d537d+_0x17ad1c(0x12c),'info');let _0x18938a=JSON['parse'](JSON[_0x17ad1c(0x10e)](_0x5a35bf[_0x17ad1c(0x1b9)][TABLE_DATA_KEY]));return _0x18938a['forEach'](_0x153a73=>{const _0x51697e=_0x17ad1c;if(_0x153a73[_0x51697e(0x199)]===undefined)_0x153a73[_0x51697e(0x199)]='无';if(_0x153a73[_0x51697e(0x198)]===undefined)_0x153a73[_0x51697e(0x198)]='允许';if(_0x153a73[_0x51697e(0x205)]===undefined)_0x153a73['rule_delete']='允许';if(_0x153a73[_0x51697e(0x18d)]===undefined)_0x153a73[_0x51697e(0x18d)]='允许';_0x153a73[_0x51697e(0x11b)]&&!_0x153a73[_0x51697e(0x16a)]&&(_0x153a73[_0x51697e(0x16a)]={},_0x153a73[_0x51697e(0x11b)][_0x51697e(0x177)]!==-0x1&&_0x153a73[_0x51697e(0x11b)][_0x51697e(0x17d)]>0x0&&(_0x153a73[_0x51697e(0x16a)][_0x153a73[_0x51697e(0x11b)][_0x51697e(0x177)]]=_0x153a73[_0x51697e(0x11b)][_0x51697e(0x17d)]));delete _0x153a73[_0x51697e(0x11b)];if(_0x153a73[_0x51697e(0x16f)]===undefined)_0x153a73[_0x51697e(0x16f)]=0x0;if(_0x153a73['columnWidths']===undefined)_0x153a73['columnWidths']=[];!_0x153a73[_0x51697e(0x1cc)]&&(_0x153a73['rowStatuses']=Array(_0x153a73[_0x51697e(0x120)]['length'])[_0x51697e(0x195)]('normal'));}),currentTablesState=_0x18938a,currentTablesState;}}}if(extension_settings[extensionName]?.[_0x17ad1c(0x1ec)]){log('未在聊天记录中找到表格,正在加载全局预设...',_0x17ad1c(0x14e));try{const _0x2f22f0=extension_settings[extensionName][_0x17ad1c(0x1ec)];return currentTablesState=JSON['parse'](JSON[_0x17ad1c(0x10e)](_0x2f22f0[_0x17ad1c(0x1dc)])),_0x2f22f0['batchFillerRuleTemplate']!==undefined&&saveBatchFillerRuleTemplate(_0x2f22f0[_0x17ad1c(0x16e)]),_0x2f22f0[_0x17ad1c(0x15e)]!==undefined&&saveBatchFillerFlowTemplate(_0x2f22f0[_0x17ad1c(0x15e)]),currentTablesState;}catch(_0x37ea60){log(_0x17ad1c(0x182)+_0x37ea60[_0x17ad1c(0x196)],_0x17ad1c(0x191));}}return log(_0x17ad1c(0x1e3),_0x17ad1c(0x14e)),currentTablesState=getDefaultTables(),currentTablesState;}export function saveStateToMessage(_0x13becb,_0x5ede24){const _0x597d3f=_0x373225;if(!_0x13becb||!_0x5ede24)return log(_0x597d3f(0x184),_0x597d3f(0x191)),![];return!_0x5ede24[_0x597d3f(0x1b9)]&&(_0x5ede24[_0x597d3f(0x1b9)]={}),_0x5ede24['extra'][TABLE_DATA_KEY]=JSON[_0x597d3f(0x155)](JSON[_0x597d3f(0x10e)](_0x13becb)),log(_0x597d3f(0x179)+_0x5ede24[_0x597d3f(0x1f6)]['substring'](0x0,0x14)+_0x597d3f(0x14b),_0x597d3f(0x14e)),!![];}export function saveTables(_0x5dfd7e='未知操作'){const _0x27fe7c=_0x373225;return log(_0x27fe7c(0x1fa)+_0x5dfd7e+_0x27fe7c(0x1ef),_0x27fe7c(0x14e)),!![];}export function deleteColumn(_0x55b1d9,_0x3dcf64){const _0x3c1d8b=_0x373225,_0x21f590=getMemoryState();if(!_0x21f590[_0x55b1d9]||_0x3dcf64<0x0||_0x3dcf64>=_0x21f590[_0x55b1d9][_0x3c1d8b(0x18c)][_0x3c1d8b(0x130)]){log(_0x3c1d8b(0x1cd)+_0x55b1d9+'\x20中找不到索引为\x20'+_0x3dcf64+_0x3c1d8b(0x1ee),_0x3c1d8b(0x191));return;}_0x21f590[_0x55b1d9][_0x3c1d8b(0x18c)][_0x3c1d8b(0x1a5)](_0x3dcf64,0x1),_0x21f590[_0x55b1d9]['rows'][_0x3c1d8b(0x1af)](_0x57a3a1=>{const _0x197d5a=_0x3c1d8b;_0x57a3a1[_0x197d5a(0x130)]>_0x3dcf64&&_0x57a3a1[_0x197d5a(0x1a5)](_0x3dcf64,0x1);}),_0x21f590[_0x55b1d9][_0x3c1d8b(0x1da)]&&_0x21f590[_0x55b1d9][_0x3c1d8b(0x1da)][_0x3c1d8b(0x130)]>_0x3dcf64&&_0x21f590[_0x55b1d9][_0x3c1d8b(0x1da)][_0x3c1d8b(0x1a5)](_0x3dcf64,0x1),log(_0x3c1d8b(0x193)+_0x55b1d9+'\x20的第\x20'+(_0x3dcf64+0x1)+'\x20列。',_0x3c1d8b(0x178)),saveTables(_0x21f590);}export function moveRow(_0x1ad4f0,_0x540f2d,_0x29006c){const _0x4fbf60=_0x373225,_0x47579c=getMemoryState(),_0x465cb0=_0x47579c[_0x1ad4f0];if(!_0x465cb0||_0x540f2d<0x0||_0x540f2d>=_0x465cb0[_0x4fbf60(0x120)]['length'])return;const _0x259dd7=_0x29006c==='up'?_0x540f2d-0x1:_0x540f2d+0x1;if(_0x259dd7<0x0||_0x259dd7>=_0x465cb0[_0x4fbf60(0x120)][_0x4fbf60(0x130)])return;const [_0x339ea4]=_0x465cb0[_0x4fbf60(0x120)][_0x4fbf60(0x1a5)](_0x540f2d,0x1);_0x465cb0[_0x4fbf60(0x120)][_0x4fbf60(0x1a5)](_0x259dd7,0x0,_0x339ea4);if(_0x465cb0['rowStatuses']&&_0x465cb0[_0x4fbf60(0x1cc)]['length']===_0x465cb0[_0x4fbf60(0x120)]['length']+0x1){const [_0x11baf6]=_0x465cb0[_0x4fbf60(0x1cc)][_0x4fbf60(0x1a5)](_0x540f2d,0x1);_0x465cb0['rowStatuses']['splice'](_0x259dd7,0x0,_0x11baf6);}log('成功将表格\x20'+_0x1ad4f0+'\x20的第\x20'+(_0x540f2d+0x1)+_0x4fbf60(0x15b)+(_0x259dd7+0x1)+_0x4fbf60(0x118),_0x4fbf60(0x178)),saveTables(_0x47579c);}export function insertRow(_0x295512,_0x1170cd,_0x2498db=_0x373225(0x1f8)){const _0x1845ab=_0x373225,_0x4a7158=getMemoryState(),_0xf8e519=_0x4a7158[_0x295512];if(!_0xf8e519){log(_0x1845ab(0x194)+_0x295512+_0x1845ab(0x13e),_0x1845ab(0x191));return;}let _0x3ab778;typeof _0x1170cd===_0x1845ab(0x1f2)?_0x3ab778=_0x2498db==='above'?_0x1170cd:_0x1170cd+0x1:_0x3ab778=_0xf8e519[_0x1845ab(0x120)][_0x1845ab(0x130)];if(_0x3ab778<0x0)_0x3ab778=0x0;if(_0x3ab778>_0xf8e519[_0x1845ab(0x120)][_0x1845ab(0x130)])_0x3ab778=_0xf8e519['rows']['length'];const _0xa27ec=new Array(_0xf8e519[_0x1845ab(0x18c)][_0x1845ab(0x130)])[_0x1845ab(0x195)]('');if(typeof _0x1170cd===_0x1845ab(0x1e2)&&_0x1170cd!==null)for(const _0x44e688 in _0x1170cd){const _0x4f381b=parseInt(_0x44e688,0xa);!isNaN(_0x4f381b)&&_0x4f381b<_0xa27ec['length']&&(_0xa27ec[_0x4f381b]=_0x1170cd[_0x44e688],addHighlight(_0x295512,_0x3ab778,_0x4f381b));}_0xf8e519[_0x1845ab(0x120)][_0x1845ab(0x1a5)](_0x3ab778,0x0,_0xa27ec);if(!_0xf8e519[_0x1845ab(0x1cc)])_0xf8e519[_0x1845ab(0x1cc)]=Array(_0xf8e519[_0x1845ab(0x120)][_0x1845ab(0x130)])[_0x1845ab(0x195)](_0x1845ab(0x141));_0xf8e519[_0x1845ab(0x1cc)][_0x1845ab(0x1a5)](_0x3ab778,0x0,'normal'),updatedTables[_0x1845ab(0x189)](_0x295512),log('成功在表格\x20'+_0xf8e519[_0x1845ab(0x1c0)]+_0x1845ab(0x11e)+_0x295512+_0x1845ab(0x128)+(_0x3ab778+0x1)+_0x1845ab(0x11c),_0x1845ab(0x178));const _0x3abcf6=getContext();if(_0x3abcf6[_0x1845ab(0x1c9)]&&_0x3abcf6[_0x1845ab(0x1c9)][_0x1845ab(0x130)]>0x0){const _0x142d09=_0x3abcf6[_0x1845ab(0x1c9)][_0x3abcf6[_0x1845ab(0x1c9)]['length']-0x1];if(saveStateToMessage(_0x4a7158,_0x142d09)){saveChat();return;}}saveChatDebounced();}export function addRow(_0x2f8220){const _0x353f6e=_0x373225;if(!currentTablesState||!currentTablesState[_0x2f8220])return;const _0x2ac5e2=currentTablesState[_0x2f8220],_0x2796a0=_0x2ac5e2[_0x353f6e(0x18c)][_0x353f6e(0x130)],_0x34480d=Array(_0x2796a0)[_0x353f6e(0x195)]('');_0x2ac5e2['rows'][_0x353f6e(0x1d0)](_0x34480d);if(!_0x2ac5e2[_0x353f6e(0x1cc)])_0x2ac5e2[_0x353f6e(0x1cc)]=Array(_0x2ac5e2[_0x353f6e(0x120)][_0x353f6e(0x130)])[_0x353f6e(0x195)](_0x353f6e(0x141));_0x2ac5e2['rowStatuses'][_0x353f6e(0x1d0)](_0x353f6e(0x141)),updatedTables['add'](_0x2f8220);const _0x3abda9=_0x353f6e(0x1b7)+_0x2ac5e2[_0x353f6e(0x1c0)]+']\x20新增了一行。';log(_0x3abda9,_0x353f6e(0x14e));const _0x2d6a50=getContext();if(_0x2d6a50['chat']&&_0x2d6a50[_0x353f6e(0x1c9)][_0x353f6e(0x130)]>0x0){const _0x16b69e=_0x2d6a50['chat'][_0x2d6a50[_0x353f6e(0x1c9)][_0x353f6e(0x130)]-0x1];if(saveStateToMessage(currentTablesState,_0x16b69e)){saveChat();return;}}saveChatDebounced();}export function addColumn(_0x5be419){const _0x57f62e=_0x373225;if(!currentTablesState||!currentTablesState[_0x5be419])return;const _0x3b7998=currentTablesState[_0x5be419],_0x2d9c7b=_0x57f62e(0x1ac)+(_0x3b7998['headers']['length']+0x1);_0x3b7998[_0x57f62e(0x18c)]['push'](_0x2d9c7b),_0x3b7998[_0x57f62e(0x120)][_0x57f62e(0x1af)](_0x1e9730=>_0x1e9730[_0x57f62e(0x1d0)](''));if(!_0x3b7998['columnWidths'])_0x3b7998['columnWidths']=[];_0x3b7998[_0x57f62e(0x1da)][_0x57f62e(0x1d0)](null);const _0x7eb1aa=_0x57f62e(0x1b7)+_0x3b7998[_0x57f62e(0x1c0)]+']\x20新增了一列。';log(_0x7eb1aa,_0x57f62e(0x14e));const _0x54ee9b=getContext();if(_0x54ee9b[_0x57f62e(0x1c9)]&&_0x54ee9b[_0x57f62e(0x1c9)]['length']>0x0){const _0x5a28b6=_0x54ee9b['chat'][_0x54ee9b['chat']['length']-0x1];if(saveStateToMessage(currentTablesState,_0x5a28b6)){saveChat();return;}}saveChatDebounced();}export function updateHeader(_0x2226f3,_0x1bbbb4,_0x3a1ec1){const _0x2003a3=_0x373225;if(!currentTablesState||!currentTablesState[_0x2226f3]||currentTablesState[_0x2226f3]['headers'][_0x1bbbb4]===undefined)return;const _0x2a4bc8=currentTablesState[_0x2226f3][_0x2003a3(0x1c0)],_0x18f017=currentTablesState[_0x2226f3][_0x2003a3(0x18c)][_0x1bbbb4];currentTablesState[_0x2226f3][_0x2003a3(0x18c)][_0x1bbbb4]=_0x3a1ec1;const _0x16d627='表格\x20['+_0x2a4bc8+_0x2003a3(0x1c8)+_0x18f017+_0x2003a3(0x204)+_0x3a1ec1+'”。';log(_0x16d627,_0x2003a3(0x14e));const _0x1a7529=getContext();if(_0x1a7529[_0x2003a3(0x1c9)]&&_0x1a7529[_0x2003a3(0x1c9)][_0x2003a3(0x130)]>0x0){const _0x337bd2=_0x1a7529[_0x2003a3(0x1c9)][_0x1a7529[_0x2003a3(0x1c9)][_0x2003a3(0x130)]-0x1];if(saveStateToMessage(currentTablesState,_0x337bd2)){saveChat();return;}}saveChatDebounced();}export async function deleteRow(_0x3a2d9b,_0x988576){const _0x21960e=_0x373225,_0x447db7=currentTablesState?.[_0x3a2d9b];if(!_0x447db7||!_0x447db7[_0x21960e(0x120)][_0x988576])return;!_0x447db7[_0x21960e(0x1cc)]&&(_0x447db7[_0x21960e(0x1cc)]=Array(_0x447db7[_0x21960e(0x120)][_0x21960e(0x130)])[_0x21960e(0x195)](_0x21960e(0x141)));_0x447db7[_0x21960e(0x1cc)][_0x988576]=_0x21960e(0x154),updatedTables['add'](_0x3a2d9b);const _0x5efed5='表格\x20['+_0x447db7['name']+_0x21960e(0x197)+(_0x988576+0x1)+_0x21960e(0x159);log(_0x5efed5,_0x21960e(0x14e));const _0x598313=getContext();if(_0x598313['chat']?.[_0x21960e(0x130)]>0x0){const _0x5e183e=_0x598313['chat'][_0x598313[_0x21960e(0x1c9)][_0x21960e(0x130)]-0x1];if(saveStateToMessage(currentTablesState,_0x5e183e)){await saveChat(),renderTables();return;}}await saveChatDebounced(),renderTables();}export async function restoreRow(_0x5c1349,_0x56db5a){const _0x41f34d=_0x373225,_0x35522f=currentTablesState?.[_0x5c1349];if(!_0x35522f||!_0x35522f[_0x41f34d(0x120)][_0x56db5a]||!_0x35522f['rowStatuses'])return;_0x35522f[_0x41f34d(0x1cc)][_0x56db5a]=_0x41f34d(0x141),updatedTables[_0x41f34d(0x189)](_0x5c1349);const _0x1970b5=_0x41f34d(0x1b7)+_0x35522f[_0x41f34d(0x1c0)]+_0x41f34d(0x197)+(_0x56db5a+0x1)+'\x20行已恢复。';log(_0x1970b5,_0x41f34d(0x14e));const _0x3118bd=getContext();if(_0x3118bd[_0x41f34d(0x1c9)]?.['length']>0x0){const _0x465d0f=_0x3118bd['chat'][_0x3118bd[_0x41f34d(0x1c9)][_0x41f34d(0x130)]-0x1];if(saveStateToMessage(currentTablesState,_0x465d0f)){await saveChat(),renderTables();return;}}await saveChatDebounced(),renderTables();}export function commitPendingDeletions(){const _0x297d9f=_0x373225;if(!currentTablesState)return![];let _0xb5528b=0x0;currentTablesState[_0x297d9f(0x1af)]((_0x51fa24,_0x10dbaa)=>{const _0x2e5095=_0x297d9f;if(!_0x51fa24[_0x2e5095(0x1cc)]||_0x51fa24[_0x2e5095(0x1cc)][_0x2e5095(0x130)]===0x0)return;let _0x10658a=![];for(let _0x40fa53=_0x51fa24[_0x2e5095(0x120)][_0x2e5095(0x130)]-0x1;_0x40fa53>=0x0;_0x40fa53--){_0x51fa24[_0x2e5095(0x1cc)][_0x40fa53]===_0x2e5095(0x154)&&(_0x51fa24[_0x2e5095(0x120)][_0x2e5095(0x1a5)](_0x40fa53,0x1),_0x51fa24[_0x2e5095(0x1cc)]['splice'](_0x40fa53,0x1),_0xb5528b++,_0x10658a=!![]);}_0x10658a&&updatedTables[_0x2e5095(0x189)](_0x10dbaa);});if(_0xb5528b>0x0)return log('已提交并永久删除了\x20'+_0xb5528b+_0x297d9f(0x118),_0x297d9f(0x14e)),!![];return![];}export function insertColumn(_0x2969ec,_0x497230,_0x30e7ce){const _0x25a858=_0x373225;if(!currentTablesState||!currentTablesState[_0x2969ec])return;const _0x4be73b=currentTablesState[_0x2969ec],_0x4ac88d=_0x30e7ce==='left'?_0x497230:_0x497230+0x1,_0x3abb4a='新列';_0x4be73b[_0x25a858(0x18c)][_0x25a858(0x1a5)](_0x4ac88d,0x0,_0x3abb4a),_0x4be73b[_0x25a858(0x120)][_0x25a858(0x1af)](_0x3c663a=>_0x3c663a['splice'](_0x4ac88d,0x0,''));if(!_0x4be73b[_0x25a858(0x1da)])_0x4be73b[_0x25a858(0x1da)]=[];_0x4be73b[_0x25a858(0x1da)][_0x25a858(0x1a5)](_0x4ac88d,0x0,null);const _0x5bce12=_0x25a858(0x1b7)+_0x4be73b[_0x25a858(0x1c0)]+']\x20在第\x20'+(_0x497230+0x1)+'\x20列的'+(_0x30e7ce===_0x25a858(0x1b6)?'左侧':'右侧')+_0x25a858(0x131);log(_0x5bce12,_0x25a858(0x14e));const _0x57f0f8=getContext();if(_0x57f0f8[_0x25a858(0x1c9)]&&_0x57f0f8[_0x25a858(0x1c9)][_0x25a858(0x130)]>0x0){const _0x194404=_0x57f0f8[_0x25a858(0x1c9)][_0x57f0f8[_0x25a858(0x1c9)][_0x25a858(0x130)]-0x1];if(saveStateToMessage(currentTablesState,_0x194404)){saveChat();return;}}saveChatDebounced();}export function moveColumn(_0x5e0612,_0x486de2,_0x5bb4f2){const _0x551479=_0x373225;if(!currentTablesState||!currentTablesState[_0x5e0612])return;const _0xfbdc80=currentTablesState[_0x5e0612],_0x4de219=_0xfbdc80[_0x551479(0x18c)],_0x4ff5f4=_0xfbdc80[_0x551479(0x120)],_0x45b007=_0x5bb4f2===_0x551479(0x1b6)?_0x486de2-0x1:_0x486de2+0x1;if(_0x45b007<0x0||_0x45b007>=_0x4de219[_0x551479(0x130)]){log(_0x551479(0x113)+_0x486de2+_0x551479(0x1f4),_0x551479(0x1d1));return;}const [_0x16cc01]=_0x4de219['splice'](_0x486de2,0x1);_0x4de219[_0x551479(0x1a5)](_0x45b007,0x0,_0x16cc01),_0x4ff5f4[_0x551479(0x1af)](_0x197523=>{const _0x3f5c1c=_0x551479,[_0x4e3d98]=_0x197523[_0x3f5c1c(0x1a5)](_0x486de2,0x1);_0x197523[_0x3f5c1c(0x1a5)](_0x45b007,0x0,_0x4e3d98);});if(_0xfbdc80[_0x551479(0x1da)]&&_0xfbdc80[_0x551479(0x1da)][_0x551479(0x130)]>_0x486de2){const [_0xe3375e]=_0xfbdc80[_0x551479(0x1da)][_0x551479(0x1a5)](_0x486de2,0x1);_0xfbdc80[_0x551479(0x1da)][_0x551479(0x1a5)](_0x45b007,0x0,_0xe3375e);}const _0x49819c=_0x551479(0x1b7)+_0xfbdc80[_0x551479(0x1c0)]+_0x551479(0x161)+_0x16cc01+_0x551479(0x14a)+(_0x5bb4f2===_0x551479(0x1b6)?'左':'右')+'移动。';log(_0x49819c,_0x551479(0x14e));const _0x2b8a7b=getContext();if(_0x2b8a7b[_0x551479(0x1c9)]&&_0x2b8a7b[_0x551479(0x1c9)][_0x551479(0x130)]>0x0){const _0x12595f=_0x2b8a7b[_0x551479(0x1c9)][_0x2b8a7b['chat'][_0x551479(0x130)]-0x1];if(saveStateToMessage(currentTablesState,_0x12595f)){saveChat();return;}}saveChatDebounced();}export function deleteTable(_0x7a9bd1){const _0x195e99=_0x373225;if(!currentTablesState||!currentTablesState[_0x7a9bd1])return;const _0x2537a2=currentTablesState[_0x7a9bd1][_0x195e99(0x1c0)];currentTablesState[_0x195e99(0x1a5)](_0x7a9bd1,0x1);const _0xbe312a=_0x195e99(0x1b7)+_0x2537a2+_0x195e99(0x1e6);log(_0xbe312a,'success');const _0x2c98d2=getContext();if(_0x2c98d2[_0x195e99(0x1c9)]&&_0x2c98d2[_0x195e99(0x1c9)][_0x195e99(0x130)]>0x0){const _0x2408a4=_0x2c98d2[_0x195e99(0x1c9)][_0x2c98d2['chat'][_0x195e99(0x130)]-0x1];if(saveStateToMessage(currentTablesState,_0x2408a4)){saveChat(),log(_0x195e99(0x1c1),'success');return;}}log(_0x195e99(0x1ff),'error'),saveChatDebounced();}export function addTable(_0x15f10b){const _0x4afac7=_0x373225;if(!_0x15f10b||!_0x15f10b[_0x4afac7(0x10c)]()){log(_0x4afac7(0x10b),_0x4afac7(0x191)),toastr[_0x4afac7(0x191)]('表格名称不能为空。','创建失败');return;}!currentTablesState&&loadTables();if(currentTablesState[_0x4afac7(0x1eb)](_0x46b4a0=>_0x46b4a0[_0x4afac7(0x1c0)]===_0x15f10b[_0x4afac7(0x10c)]())){log(_0x4afac7(0x1c6)+_0x15f10b+_0x4afac7(0x1d6),_0x4afac7(0x191)),toastr[_0x4afac7(0x191)](_0x4afac7(0x1a6)+_0x15f10b+'\x22\x20的表格已存在。',_0x4afac7(0x1e7));return;}const _0x4895a6={'name':_0x15f10b[_0x4afac7(0x10c)](),'headers':[_0x4afac7(0x11a)],'rows':[],'rowStatuses':[],'columnWidths':[],'note':_0x4afac7(0x1ed),'rule_add':'允许','rule_delete':'允许','rule_update':'允许','charLimitRules':{},'rowLimitRule':0x0};currentTablesState[_0x4afac7(0x1d0)](_0x4895a6);const _0x416ce9=_0x4afac7(0x125)+_0x15f10b[_0x4afac7(0x10c)]()+']。';log(_0x416ce9,_0x4afac7(0x178));const _0x354f16=getContext();if(_0x354f16[_0x4afac7(0x1c9)]&&_0x354f16['chat']['length']>0x0){const _0x5dbad6=_0x354f16[_0x4afac7(0x1c9)][_0x354f16['chat'][_0x4afac7(0x130)]-0x1];if(saveStateToMessage(currentTablesState,_0x5dbad6)){saveChat(),log('新表格状态已强制写入最新消息并立即保存。','success');return;}}log(_0x4afac7(0x1e5),_0x4afac7(0x191)),saveChatDebounced();}export function renameTable(_0x1a1824,_0x209595){const _0x55f484=_0x373225;if(!currentTablesState||!currentTablesState[_0x1a1824]){log(_0x55f484(0x151),_0x55f484(0x191)),toastr['error'](_0x55f484(0x144),'重命名失败');return;}const _0x3750ec=_0x209595['trim']();if(!_0x3750ec){log('重命名失败:名称不能为空。','error'),toastr[_0x55f484(0x191)]('表格名称不能为空。',_0x55f484(0x19f));return;}if(currentTablesState['some']((_0x16088a,_0x7ab834)=>_0x7ab834!==_0x1a1824&&_0x16088a[_0x55f484(0x1c0)]===_0x3750ec)){log('重命名失败:名为\x20\x22'+_0x3750ec+_0x55f484(0x1d6),_0x55f484(0x191)),toastr[_0x55f484(0x191)](_0x55f484(0x1a6)+_0x3750ec+'\x22\x20的表格已存在。',_0x55f484(0x19f));return;}const _0x24b43f=currentTablesState[_0x1a1824]['name'];currentTablesState[_0x1a1824][_0x55f484(0x1c0)]=_0x3750ec,log(_0x55f484(0x112)+_0x24b43f+'\x22\x20已重命名为\x20\x22'+_0x3750ec+'\x22。',_0x55f484(0x178));const _0x2ba99d=getContext();if(_0x2ba99d[_0x55f484(0x1c9)]&&_0x2ba99d['chat'][_0x55f484(0x130)]>0x0){const _0x1d7878=_0x2ba99d['chat'][_0x2ba99d[_0x55f484(0x1c9)][_0x55f484(0x130)]-0x1];if(saveStateToMessage(currentTablesState,_0x1d7878)){saveChat();return;}}saveChatDebounced();}export function moveTable(_0x3f7152,_0x5f4f9b){const _0x5c59b8=_0x373225;if(!currentTablesState||!currentTablesState[_0x3f7152])return;const _0x2728b8=_0x5f4f9b==='up'?_0x3f7152-0x1:_0x3f7152+0x1;if(_0x2728b8<0x0||_0x2728b8>=currentTablesState[_0x5c59b8(0x130)]){log(_0x5c59b8(0x153)+_0x3f7152+_0x5c59b8(0x1f4),_0x5c59b8(0x1d1));return;}const _0x251bd2=currentTablesState[_0x3f7152];currentTablesState[_0x3f7152]=currentTablesState[_0x2728b8],currentTablesState[_0x2728b8]=_0x251bd2;const _0x3c1cdb='表格\x20['+_0x251bd2[_0x5c59b8(0x1c0)]+_0x5c59b8(0x201);log(_0x3c1cdb,'success');const _0x59a33c=getContext();if(_0x59a33c[_0x5c59b8(0x1c9)]&&_0x59a33c[_0x5c59b8(0x1c9)][_0x5c59b8(0x130)]>0x0){const _0x13f4ea=_0x59a33c['chat'][_0x59a33c[_0x5c59b8(0x1c9)]['length']-0x1];if(saveStateToMessage(currentTablesState,_0x13f4ea)){saveChat(),log('表格顺序调整后的状态已强制写入最新消息并立即保存。',_0x5c59b8(0x178));return;}}log(_0x5c59b8(0x15d),'error'),saveChatDebounced();}export function updateTableRules(_0x2be7e3,_0xad0f1f){const _0x54012b=_0x373225;if(!currentTablesState||!currentTablesState[_0x2be7e3])return;const _0x2e2be5=currentTablesState[_0x2be7e3];_0x2e2be5[_0x54012b(0x199)]=_0xad0f1f[_0x54012b(0x199)],_0x2e2be5[_0x54012b(0x198)]=_0xad0f1f[_0x54012b(0x198)],_0x2e2be5['rule_delete']=_0xad0f1f[_0x54012b(0x205)],_0x2e2be5[_0x54012b(0x18d)]=_0xad0f1f[_0x54012b(0x18d)],_0x2e2be5[_0x54012b(0x16a)]=_0xad0f1f['charLimitRules'],_0x2e2be5[_0x54012b(0x16f)]=_0xad0f1f[_0x54012b(0x16f)],delete _0x2e2be5[_0x54012b(0x11b)];const _0x1997ca='表格\x20['+_0x2e2be5[_0x54012b(0x1c0)]+_0x54012b(0x17c);log(_0x1997ca,_0x54012b(0x14e));const _0x3713ad=getContext();if(_0x3713ad[_0x54012b(0x1c9)]&&_0x3713ad[_0x54012b(0x1c9)]['length']>0x0){const _0x3bd6b2=_0x3713ad['chat'][_0x3713ad[_0x54012b(0x1c9)][_0x54012b(0x130)]-0x1];if(saveStateToMessage(currentTablesState,_0x3bd6b2)){saveChat();return;}}saveChatDebounced();}export function updateRow(_0x5337d1,_0x3bce00,_0x1105fd){const _0x1fbcfd=_0x373225;if(!currentTablesState||!currentTablesState[_0x5337d1]){log(_0x1fbcfd(0x13a)+_0x5337d1+_0x1fbcfd(0x1ce),'error');return;}const _0x433c26=currentTablesState[_0x5337d1];if(_0x3bce00>=_0x433c26[_0x1fbcfd(0x120)][_0x1fbcfd(0x130)]){log(_0x1fbcfd(0x12f)+_0x3bce00+'),已智能转换为在表格\x20['+_0x433c26[_0x1fbcfd(0x1c0)]+_0x1fbcfd(0x1fb),_0x1fbcfd(0x1d1)),insertRow(_0x5337d1,_0x1105fd);return;}const _0x4c46ff=_0x433c26[_0x1fbcfd(0x120)][_0x3bce00];for(const _0x24f69a in _0x1105fd){const _0x2b7530=parseInt(_0x24f69a,0xa);_0x2b7530<_0x4c46ff[_0x1fbcfd(0x130)]&&(_0x4c46ff[_0x2b7530]=_0x1105fd[_0x2b7530],addHighlight(_0x5337d1,_0x3bce00,_0x2b7530));}updatedTables['add'](_0x5337d1);const _0x28c364=_0x1fbcfd(0x106)+_0x433c26['name']+_0x1fbcfd(0x197)+(_0x3bce00+0x1)+_0x1fbcfd(0x118);log(_0x28c364,_0x1fbcfd(0x14e));const _0x564a4a=getContext();if(_0x564a4a[_0x1fbcfd(0x1c9)]&&_0x564a4a[_0x1fbcfd(0x1c9)][_0x1fbcfd(0x130)]>0x0){const _0x2807bc=_0x564a4a[_0x1fbcfd(0x1c9)][_0x564a4a[_0x1fbcfd(0x1c9)][_0x1fbcfd(0x130)]-0x1];if(saveStateToMessage(currentTablesState,_0x2807bc)){saveChat();return;}}saveChatDebounced();}export function clearAllTables(){const _0x5cce5c=_0x373225;if(!currentTablesState){log(_0x5cce5c(0x169),_0x5cce5c(0x191));return;}currentTablesState[_0x5cce5c(0x1af)]((_0x1fa511,_0x467623)=>{const _0x3e09aa=_0x5cce5c;_0x1fa511['rows'][_0x3e09aa(0x130)]>0x0&&updatedTables[_0x3e09aa(0x189)](_0x467623),_0x1fa511[_0x3e09aa(0x120)]=[],_0x1fa511[_0x3e09aa(0x1cc)]=[];}),log('所有表格的行数据已在内存中清空。',_0x5cce5c(0x1d1));const _0x6040b5=getContext();if(_0x6040b5[_0x5cce5c(0x1c9)]&&_0x6040b5['chat'][_0x5cce5c(0x130)]>0x0){const _0x5b4891=_0x6040b5['chat'][_0x6040b5[_0x5cce5c(0x1c9)][_0x5cce5c(0x130)]-0x1];if(saveStateToMessage(currentTablesState,_0x5b4891)){saveChat(),log('清空行数据后的状态已强制写入最新消息并立即保存。',_0x5cce5c(0x178)),toastr[_0x5cce5c(0x178)](_0x5cce5c(0x111),_0x5cce5c(0x19b));return;}}log(_0x5cce5c(0x1f3),_0x5cce5c(0x191)),saveChatDebounced();}function checkTableRules(_0x657002){const _0x5bd2ad=_0x373225;let _0x4c8b39=[];_0x657002[_0x5bd2ad(0x16f)]&&_0x657002[_0x5bd2ad(0x16f)]>0x0&&_0x657002[_0x5bd2ad(0x120)][_0x5bd2ad(0x130)]>_0x657002[_0x5bd2ad(0x16f)]&&_0x4c8b39[_0x5bd2ad(0x1d0)](_0x5bd2ad(0x107)+_0x657002[_0x5bd2ad(0x1c0)]+_0x5bd2ad(0x1fd)+_0x657002['rowLimitRule']+_0x5bd2ad(0x1fc)+_0x657002['rowLimitRule']+_0x5bd2ad(0x12b));const _0x3a7cb5=_0x657002['charLimitRules']||{};for(const _0x4d2ec1 in _0x3a7cb5){const _0x2da230=parseInt(_0x4d2ec1,0xa),_0x37f154=_0x3a7cb5[_0x2da230];if(_0x37f154>0x0&&_0x2da230>=0x0&&_0x2da230<_0x657002[_0x5bd2ad(0x18c)][_0x5bd2ad(0x130)]){const _0x2a4155=_0x657002[_0x5bd2ad(0x18c)][_0x2da230],_0x5a4efa=[];_0x657002[_0x5bd2ad(0x120)]['forEach']((_0x2b14f8,_0x32f6ee)=>{const _0x2eaa0b=_0x5bd2ad;if(_0x657002[_0x2eaa0b(0x1cc)]&&_0x657002[_0x2eaa0b(0x1cc)][_0x32f6ee]===_0x2eaa0b(0x154))return;const _0x21b6c6=_0x2b14f8[_0x2da230]||'';_0x21b6c6[_0x2eaa0b(0x130)]>_0x37f154&&_0x5a4efa[_0x2eaa0b(0x1d0)](_0x32f6ee);});if(_0x5a4efa[_0x5bd2ad(0x130)]>0x0){const _0x2f5a64=_0x5a4efa[_0x5bd2ad(0x172)]('、');_0x4c8b39['push'](_0x5bd2ad(0x107)+_0x657002[_0x5bd2ad(0x1c0)]+_0x5bd2ad(0x121)+_0x2f5a64+_0x5bd2ad(0x1b0)+_0x2a4155+_0x5bd2ad(0x115)+_0x37f154+_0x5bd2ad(0x1ca));}}}return _0x4c8b39[_0x5bd2ad(0x172)]('\x0a');}export function convertTablesToCsvString(){const _0x3ba957=_0x373225;!currentTablesState&&loadTables();if(!currentTablesState)return'';let _0x3a4154='';return currentTablesState[_0x3ba957(0x1af)]((_0x360180,_0x8b7521)=>{const _0x3c3880=_0x3ba957;_0x3a4154+=_0x3c3880(0x1c2)+_0x8b7521+':'+_0x360180['name']+'\x0a',_0x3a4154+=_0x3c3880(0x1e9)+(_0x360180[_0x3c3880(0x199)]||'无')+'\x0a';const _0x30033f=_0x360180[_0x3c3880(0x1c0)]['replace'](/\s/g,'')+'内容';_0x3a4154+='<'+_0x30033f+'>\x0a';const _0x237579=_0x360180[_0x3c3880(0x18c)]['map']((_0x17e539,_0x2dcaca)=>_0x2dcaca+':'+_0x17e539)['join'](',');_0x3a4154+=_0x3c3880(0x10d)+_0x237579+'\x0a';_0x360180['rows']['length']===0x0||_0x360180[_0x3c3880(0x120)]['every']((_0x4c2d6d,_0xe92f22)=>_0x360180['rowStatuses']&&_0x360180[_0x3c3880(0x1cc)][_0xe92f22]===_0x3c3880(0x154))?_0x3a4154+='(该表当前内容为空)\x0a':_0x360180['rows'][_0x3c3880(0x1af)]((_0x30ec44,_0x2cad0f)=>{const _0x3be45e=_0x3c3880;if(_0x360180[_0x3be45e(0x1cc)]&&_0x360180[_0x3be45e(0x1cc)][_0x2cad0f]==='pending-deletion')return;if(Array['isArray'](_0x30ec44)){const _0x1e7f20=_0x30ec44[_0x3be45e(0x1c5)](_0x504172=>{const _0x27059e=_0x3be45e;return _0x504172===null||_0x504172===undefined||_0x504172===''?'未知':_0x504172[_0x27059e(0x15f)]();})[_0x3be45e(0x172)](',');_0x3a4154+=_0x2cad0f+','+_0x1e7f20+'\x0a';}});const _0x480e7f=checkTableRules(_0x360180);_0x480e7f&&(_0x3a4154+=_0x480e7f+'\x0a'),_0x3a4154+=''+_0x30033f+'>\x0a',_0x3a4154+=_0x3c3880(0x1bd)+(_0x360180[_0x3c3880(0x198)]||'允许')+'\x0a',_0x3a4154+=_0x3c3880(0x10a)+(_0x360180[_0x3c3880(0x205)]||'允许')+'\x0a',_0x3a4154+='【修改】:\x20'+(_0x360180['rule_update']||'允许')+'\x0a',_0x8b7521{const _0x5deb97=_0x2e82cb;_0x29d7c4+='\x0a<'+_0x5e6b1b[_0x5deb97(0x1c0)]+'>\x0a';const _0x1ee771=_0x5e6b1b[_0x5deb97(0x18c)][_0x5deb97(0x1c5)]((_0x384ffc,_0x5248af)=>String['fromCharCode'](0x41+_0x5248af)+':'+_0x384ffc)[_0x5deb97(0x172)](',');_0x29d7c4+=_0x1ee771+'\x0a';const _0x551152=_0x5e6b1b['rows']['filter']((_0x43aca1,_0x1149a1)=>!_0x5e6b1b['rowStatuses']||_0x5e6b1b[_0x5deb97(0x1cc)][_0x1149a1]!=='pending-deletion');_0x551152[_0x5deb97(0x130)]>0x0?_0x551152[_0x5deb97(0x1af)]((_0xbca138,_0x25672f)=>{const _0x4089b0=_0x5deb97;if(Array['isArray'](_0xbca138)){const _0x670cdf=_0xbca138[_0x4089b0(0x172)](','),_0x2b3f92=_0x5e6b1b[_0x4089b0(0x120)][_0x4089b0(0x19c)](_0xbca138);_0x29d7c4+=_0x2b3f92+0x1+':'+_0x670cdf+'\x0a';}}):_0x29d7c4+='(该表当前内容为空)\x0a',_0x29d7c4+=''+_0x5e6b1b[_0x5deb97(0x1c0)]+'>\x0a';}),_0x29d7c4['trim']();}loadTables();export function getBatchFillerRuleTemplate(){return extension_settings[extensionName]?.['batch_filler_rule_template']??DEFAULT_AI_RULE_TEMPLATE;}export function saveBatchFillerRuleTemplate(_0x4872b2){const _0x41ec1a=_0x373225;extension_settings[extensionName][_0x41ec1a(0x1d9)]=_0x4872b2,saveSettingsDebounced();}export function getBatchFillerFlowTemplate(){const _0x5b08d9=_0x373225;return extension_settings[extensionName]?.[_0x5b08d9(0x101)]??DEFAULT_AI_FLOW_TEMPLATE;}export function saveBatchFillerFlowTemplate(_0x1751ba){const _0x5673c6=_0x373225;extension_settings[extensionName][_0x5673c6(0x101)]=_0x1751ba,saveSettingsDebounced();}export function getAiFlowTemplateForInjection(){const _0x53b302=_0x373225;return extension_settings[extensionName]?.[_0x53b302(0x1b3)]??DEFAULT_AI_FLOW_TEMPLATE;}export async function updateTableFromText(_0x4a3629){const _0x545e83=_0x373225;if(!_0x4a3629){log(_0x545e83(0x1b5),_0x545e83(0x1d1));return;}const _0x2cab68=_0x4a3629['match'](/([\s\S]*?)<\/Amily2Edit>/);if(!_0x2cab68||!_0x2cab68[0x1]){log(_0x545e83(0x1f5),_0x545e83(0x1d1));return;}let _0xe3bf4=_0x2cab68[0x1][_0x545e83(0x135)](//g,'')[_0x545e83(0x10c)]();if(!_0xe3bf4){log(_0x545e83(0x1c4),_0x545e83(0x14e));return;}const _0x472275=_0xe3bf4[_0x545e83(0x146)]('\x0a')[_0x545e83(0x206)](_0x1ec43f=>_0x1ec43f[_0x545e83(0x10c)]()!=='');log(_0x545e83(0x1be)+_0x472275['length']+_0x545e83(0x16c),_0x545e83(0x14e));const _0x354dbf={'insertRow':(_0x19b0db,_0x410929)=>{const _0x2cb702=_0x545e83;log(_0x2cb702(0x1d8)+_0x19b0db+',\x20data='+JSON['stringify'](_0x410929)+')',_0x2cb702(0x14e)),insertRow(_0x19b0db,_0x410929);},'deleteRow':(_0x1d204b,_0x8b3706)=>{const _0x3e6a3d=_0x545e83;log(_0x3e6a3d(0x1b1)+_0x1d204b+',\x20rowIndex='+_0x8b3706+')',_0x3e6a3d(0x14e)),deleteRow(_0x1d204b,_0x8b3706);},'updateRow':(_0x3ec711,_0xd15ecb,_0x55f0c9)=>{const _0x2f42e2=_0x545e83;log('执行AI指令:\x20updateRow(tableIndex='+_0x3ec711+_0x2f42e2(0x104)+_0xd15ecb+_0x2f42e2(0x175)+JSON[_0x2f42e2(0x10e)](_0x55f0c9)+')','info'),updateRow(_0x3ec711,_0xd15ecb,_0x55f0c9);}};try{const _0x495c5a=Object[_0x545e83(0x1f0)](async function(){})[_0x545e83(0x14c)],_0x149dd2=new _0x495c5a(_0x545e83(0x126),_0x545e83(0x127)+_0xe3bf4+_0x545e83(0x18b));await _0x149dd2(_0x354dbf),log('所有AI指令已成功执行完毕。',_0x545e83(0x178)),toastr[_0x545e83(0x178)](_0x545e83(0x152),_0x545e83(0x116)),document['dispatchEvent'](new CustomEvent(_0x545e83(0x1e1)));}catch(_0x7b3204){log(_0x545e83(0x105)+_0x7b3204[_0x545e83(0x196)],_0x545e83(0x191)),toastr[_0x545e83(0x191)]('执行AI指令时出错:\x20'+_0x7b3204[_0x545e83(0x196)],_0x545e83(0x157));}}export function saveAiTemplate(_0x827724){const _0x17d5c5=_0x373225;extension_settings[extensionName][_0x17d5c5(0x1b3)]=_0x827724,saveSettingsDebounced();}function _0x4c40(_0x1d17c2,_0x59ba13){const _0x162f90=_0x162f();return _0x4c40=function(_0x4c4064,_0x49c98d){_0x4c4064=_0x4c4064-0x101;let _0x908124=_0x162f90[_0x4c4064];return _0x908124;},_0x4c40(_0x1d17c2,_0x59ba13);}export function getAiTemplate(){return getAiFlowTemplateForInjection();}function exportPresetBase(_0x42f269=![]){const _0x42acbc=_0x373225;if(!currentTablesState){log(_0x42acbc(0x19e),'error'),toastr[_0x42acbc(0x191)]('没有可导出的表格数据。');return;}let _0x361a1f,_0x3c84d9,_0xe418bb;_0x42f269?(_0x361a1f=JSON[_0x42acbc(0x155)](JSON[_0x42acbc(0x10e)](currentTablesState)),_0x3c84d9=_0x42acbc(0x158),_0xe418bb=_0x42acbc(0x17e)):(_0x361a1f=currentTablesState[_0x42acbc(0x1c5)](_0x3b8732=>({'name':_0x3b8732[_0x42acbc(0x1c0)],'headers':_0x3b8732[_0x42acbc(0x18c)],'columnWidths':_0x3b8732[_0x42acbc(0x1da)]||[],'note':_0x3b8732[_0x42acbc(0x199)],'rule_add':_0x3b8732['rule_add'],'rule_delete':_0x3b8732[_0x42acbc(0x205)],'rule_update':_0x3b8732[_0x42acbc(0x18d)],'charLimitRules':_0x3b8732['charLimitRules']||{},'rowLimitRule':_0x3b8732[_0x42acbc(0x16f)]||0x0,'rows':[],'rowStatuses':[]})),_0x3c84d9=_0x42acbc(0x156),_0xe418bb=_0x42acbc(0x16d));const _0x78a6b4={'version':_0x42acbc(0x145),'batchFillerRuleTemplate':getBatchFillerRuleTemplate(),'batchFillerFlowTemplate':getBatchFillerFlowTemplate(),'tables':_0x361a1f},_0x57d598=new Blob([JSON['stringify'](_0x78a6b4,null,0x2)],{'type':'application/json'}),_0x5f3dea=URL[_0x42acbc(0x149)](_0x57d598),_0x17551a=document['createElement']('a');_0x17551a[_0x42acbc(0x1a3)]=_0x5f3dea,_0x17551a[_0x42acbc(0x1f9)]=_0x42acbc(0x1d7)+_0xe418bb+'-'+new Date()['toISOString']()['slice'](0x0,0xa)+'.json',document[_0x42acbc(0x1df)][_0x42acbc(0x14f)](_0x17551a),_0x17551a[_0x42acbc(0x174)](),document[_0x42acbc(0x1df)][_0x42acbc(0x1a8)](_0x17551a),URL[_0x42acbc(0x1ba)](_0x5f3dea),log('【'+_0xe418bb+_0x42acbc(0x139),_0x42acbc(0x178)),toastr[_0x42acbc(0x178)]('【'+_0xe418bb+_0x42acbc(0x129),'导出成功');}export function exportPreset(){exportPresetBase(![]);}export function exportPresetFull(){exportPresetBase(!![]);}export function importPreset(_0x25de51){const _0x493983=_0x373225,_0x372acd=document[_0x493983(0x1f1)](_0x493983(0x11f));_0x372acd[_0x493983(0x15c)]=_0x493983(0x203),_0x372acd[_0x493983(0x12a)]=_0x493983(0x1b4),_0x372acd['onchange']=_0x5aa18d=>{const _0x2f9252=_0x493983,_0x1c2adf=_0x5aa18d[_0x2f9252(0x16b)]['files'][0x0];if(!_0x1c2adf)return;const _0x3259ac=new FileReader();_0x3259ac['onload']=_0x3914d7=>{const _0x8e6e78=_0x2f9252;try{const _0x368b71=JSON[_0x8e6e78(0x155)](_0x3914d7[_0x8e6e78(0x16b)][_0x8e6e78(0x1a7)]);if(!_0x368b71[_0x8e6e78(0x12e)]||!Array[_0x8e6e78(0x1cf)](_0x368b71['tables']))throw new Error('文件格式无效或缺少版本号/表格数据。');const _0x170f61=window['confirm'](_0x8e6e78(0x1c7));if(!_0x170f61){log('用户取消了导入操作。',_0x8e6e78(0x14e)),toastr[_0x8e6e78(0x14e)]('导入操作已取消。');return;}if(_0x368b71[_0x8e6e78(0x12e)]===_0x8e6e78(0x145))saveBatchFillerRuleTemplate(_0x368b71[_0x8e6e78(0x16e)]||''),saveBatchFillerFlowTemplate(_0x368b71['batchFillerFlowTemplate']||''),saveAiTemplate(_0x368b71[_0x8e6e78(0x1ad)]||'');else{if(_0x368b71[_0x8e6e78(0x1a0)]!==undefined&&_0x368b71[_0x8e6e78(0x190)]!==undefined)saveBatchFillerRuleTemplate(_0x368b71[_0x8e6e78(0x1a0)]||''),saveBatchFillerFlowTemplate(_0x368b71[_0x8e6e78(0x190)]||''),saveAiTemplate(_0x368b71[_0x8e6e78(0x190)]||'');else _0x368b71[_0x8e6e78(0x180)]?(saveBatchFillerRuleTemplate(''),saveBatchFillerFlowTemplate(_0x368b71[_0x8e6e78(0x180)]||''),saveAiTemplate(_0x368b71[_0x8e6e78(0x180)]||'')):log(_0x8e6e78(0x110),_0x8e6e78(0x1d1));}const _0x1a61f9=_0x368b71[_0x8e6e78(0x1dc)];_0x1a61f9['forEach'](_0x168c4b=>{const _0x2fbfff=_0x8e6e78;if(_0x168c4b[_0x2fbfff(0x1c0)]===undefined||_0x168c4b[_0x2fbfff(0x18c)]===undefined||_0x168c4b[_0x2fbfff(0x120)]===undefined)throw new Error(_0x2fbfff(0x137)+JSON[_0x2fbfff(0x10e)](_0x168c4b));if(_0x168c4b[_0x2fbfff(0x199)]===undefined)_0x168c4b[_0x2fbfff(0x199)]='无';if(_0x168c4b['rule_add']===undefined)_0x168c4b['rule_add']='允许';if(_0x168c4b[_0x2fbfff(0x205)]===undefined)_0x168c4b[_0x2fbfff(0x205)]='允许';if(_0x168c4b[_0x2fbfff(0x18d)]===undefined)_0x168c4b['rule_update']='允许';if(_0x168c4b[_0x2fbfff(0x11b)]&&!_0x168c4b['charLimitRules'])_0x168c4b[_0x2fbfff(0x16a)]={},_0x168c4b[_0x2fbfff(0x11b)]['columnIndex']!==-0x1&&_0x168c4b[_0x2fbfff(0x11b)][_0x2fbfff(0x17d)]>0x0&&(_0x168c4b[_0x2fbfff(0x16a)][_0x168c4b[_0x2fbfff(0x11b)][_0x2fbfff(0x177)]]=_0x168c4b['charLimitRule'][_0x2fbfff(0x17d)]);else _0x168c4b[_0x2fbfff(0x16a)]===undefined&&(_0x168c4b['charLimitRules']={});delete _0x168c4b[_0x2fbfff(0x11b)],!_0x168c4b['rowStatuses']&&(_0x168c4b['rowStatuses']=Array(_0x168c4b[_0x2fbfff(0x120)][_0x2fbfff(0x130)])[_0x2fbfff(0x195)](_0x2fbfff(0x141))),_0x168c4b[_0x2fbfff(0x16f)]===undefined&&(_0x168c4b[_0x2fbfff(0x16f)]=0x0),_0x168c4b[_0x2fbfff(0x1da)]===undefined&&(_0x168c4b[_0x2fbfff(0x1da)]=[]);}),setMemoryState(_0x1a61f9);const _0x575ef5=getContext();if(_0x575ef5[_0x8e6e78(0x1c9)]&&_0x575ef5[_0x8e6e78(0x1c9)][_0x8e6e78(0x130)]>0x0){const _0x536a86=_0x575ef5['chat'][_0x575ef5[_0x8e6e78(0x1c9)][_0x8e6e78(0x130)]-0x1];saveStateToMessage(getMemoryState(),_0x536a86)&&(saveChat(),log(_0x8e6e78(0x1de),'success'));}else saveChatDebounced();log(_0x8e6e78(0x186),_0x8e6e78(0x178)),toastr['success']('预设已成功导入!',_0x8e6e78(0x1e4)),typeof _0x25de51==='function'&&_0x25de51();}catch(_0x4f7ae){log(_0x8e6e78(0x188)+_0x4f7ae[_0x8e6e78(0x196)],'error'),toastr[_0x8e6e78(0x191)](_0x8e6e78(0x1c3)+_0x4f7ae[_0x8e6e78(0x196)],'错误');}},_0x3259ac[_0x2f9252(0x117)](_0x1c2adf);},_0x372acd[_0x493983(0x174)]();}export async function rollbackState(){const _0x43af7e=_0x373225,_0x20654d=getContext();if(!_0x20654d||!_0x20654d[_0x43af7e(0x1c9)]||_0x20654d[_0x43af7e(0x1c9)][_0x43af7e(0x130)]<0x2)return log(_0x43af7e(0x1bf),_0x43af7e(0x1d1)),toastr['warning'](_0x43af7e(0x10f)),![];const _0x11a86e=_0x20654d[_0x43af7e(0x1c9)],_0x2e24bd=_0x11a86e[_0x43af7e(0x130)]-0x1,_0x4142ae=_0x11a86e[_0x2e24bd];log(_0x43af7e(0x124)+(_0x2e24bd-0x1)+_0x43af7e(0x1ea),'info');const _0x33ee25=loadTables(_0x2e24bd);if(!_0x33ee25)return log('未能在上一楼找到可用的表格状态,无法回退。','error'),toastr[_0x43af7e(0x191)]('未能在上一楼找到可用的表格状态。'),![];setMemoryState(_0x33ee25);if(saveStateToMessage(_0x33ee25,_0x4142ae))await saveChat(),log(_0x43af7e(0x164),_0x43af7e(0x178));else return log(_0x43af7e(0x171),_0x43af7e(0x191)),toastr[_0x43af7e(0x191)]('未能保存回退状态,操作中止。'),![];return renderTables(),updateOrInsertTableInChat(),log(_0x43af7e(0x114),'info'),!![];}export async function rollbackAndRefill(){const _0x3d0cf2=_0x373225;toastr[_0x3d0cf2(0x14e)](_0x3d0cf2(0x1cb));const _0x1baf39=await rollbackState();if(!_0x1baf39){toastr[_0x3d0cf2(0x191)](_0x3d0cf2(0x1d4));return;}toastr[_0x3d0cf2(0x178)](_0x3d0cf2(0x162));const _0x35e43d=getContext(),_0x2d479c=_0x35e43d[_0x3d0cf2(0x1c9)][_0x35e43d[_0x3d0cf2(0x1c9)][_0x3d0cf2(0x130)]-0x1];try{await fillWithSecondaryApi(_0x2d479c,!![]),log(_0x3d0cf2(0x1d5),_0x3d0cf2(0x178));}catch(_0x370fde){log(_0x3d0cf2(0x1a4)+_0x370fde[_0x3d0cf2(0x196)],_0x3d0cf2(0x191)),toastr[_0x3d0cf2(0x191)](_0x3d0cf2(0x19a)+_0x370fde[_0x3d0cf2(0x196)]);}}export function updateColumnWidth(_0x46ea10,_0x4d416d,_0x131746){const _0x3f925d=_0x373225;if(!currentTablesState||!currentTablesState[_0x46ea10])return;const _0x40afde=currentTablesState[_0x46ea10];!_0x40afde['columnWidths']&&(_0x40afde[_0x3f925d(0x1da)]=[]);while(_0x40afde[_0x3f925d(0x1da)][_0x3f925d(0x130)]<_0x40afde[_0x3f925d(0x18c)][_0x3f925d(0x130)]){_0x40afde['columnWidths']['push'](null);}_0x40afde[_0x3f925d(0x1da)][_0x4d416d]=_0x131746;const _0x206778=getContext();if(_0x206778[_0x3f925d(0x1c9)]&&_0x206778['chat']['length']>0x0){const _0xfffaa9=_0x206778[_0x3f925d(0x1c9)][_0x206778[_0x3f925d(0x1c9)][_0x3f925d(0x130)]-0x1];if(saveStateToMessage(currentTablesState,_0xfffaa9)){saveChat();return;}}saveChatDebounced();}export function isCurrentTablesEmpty(){const _0x1127af=_0x373225,_0x4ca1bb=getMemoryState();if(!_0x4ca1bb||_0x4ca1bb[_0x1127af(0x130)]===0x0)return!![];return _0x4ca1bb[_0x1127af(0x1e8)](_0x5759ce=>!_0x5759ce[_0x1127af(0x120)]||_0x5759ce[_0x1127af(0x120)][_0x1127af(0x130)]===0x0);}export function clearGlobalPreset(){const _0x31a974=_0x373225;if(extension_settings[extensionName]&&extension_settings[extensionName][_0x31a974(0x1ec)]){const _0xda6e51=window[_0x31a974(0x19d)](_0x31a974(0x148));_0xda6e51?(delete extension_settings[extensionName]['global_table_preset'],saveSettingsDebounced(),log(_0x31a974(0x138),_0x31a974(0x178)),toastr[_0x31a974(0x178)](_0x31a974(0x123),_0x31a974(0x1b8))):(log(_0x31a974(0x142),_0x31a974(0x14e)),toastr[_0x31a974(0x14e)]('操作已取消。'));}else log(_0x31a974(0x150),_0x31a974(0x14e)),toastr[_0x31a974(0x14e)](_0x31a974(0x176),'提示');}export function importGlobalPreset(_0x5a1455){const _0x5c1140=_0x373225,_0x1d0349=document[_0x5c1140(0x1f1)](_0x5c1140(0x11f));_0x1d0349['type']=_0x5c1140(0x203),_0x1d0349[_0x5c1140(0x12a)]=_0x5c1140(0x1b4),_0x1d0349[_0x5c1140(0x134)]=_0x39a6ef=>{const _0x55898a=_0x5c1140,_0x1b23bf=_0x39a6ef[_0x55898a(0x16b)][_0x55898a(0x1b2)][0x0];if(!_0x1b23bf)return;const _0x420294=new FileReader();_0x420294[_0x55898a(0x11d)]=_0x227325=>{const _0x541dbd=_0x55898a;try{const _0x44030c=JSON[_0x541dbd(0x155)](_0x227325['target'][_0x541dbd(0x1a7)]);if(!_0x44030c[_0x541dbd(0x12e)]||!Array[_0x541dbd(0x1cf)](_0x44030c['tables']))throw new Error(_0x541dbd(0x163));const _0x3008f3=window[_0x541dbd(0x19d)](_0x541dbd(0x108));if(!_0x3008f3){log('用户取消了全局预设导入操作。',_0x541dbd(0x14e)),toastr['info'](_0x541dbd(0x14d));return;}const _0x3479bf=_0x44030c[_0x541dbd(0x1dc)]['map'](_0x41e941=>({'name':_0x41e941[_0x541dbd(0x1c0)],'headers':_0x41e941['headers'],'note':_0x41e941['note'],'rule_add':_0x41e941[_0x541dbd(0x198)],'rule_delete':_0x41e941['rule_delete'],'rule_update':_0x41e941[_0x541dbd(0x18d)],'rows':[]}));!extension_settings[extensionName]&&(extension_settings[extensionName]={});extension_settings[extensionName][_0x541dbd(0x1ec)]={'version':_0x44030c['version'],'tables':_0x3479bf,'batchFillerRuleTemplate':_0x44030c['batchFillerRuleTemplate'],'batchFillerFlowTemplate':_0x44030c[_0x541dbd(0x15e)]},saveSettingsDebounced();if(_0x44030c['version']===_0x541dbd(0x145))saveBatchFillerRuleTemplate(_0x44030c[_0x541dbd(0x16e)]||''),saveBatchFillerFlowTemplate(_0x44030c['batchFillerFlowTemplate']||''),saveAiTemplate(_0x44030c[_0x541dbd(0x1ad)]||'');else{if(_0x44030c[_0x541dbd(0x1a0)]!==undefined&&_0x44030c[_0x541dbd(0x190)]!==undefined)saveBatchFillerRuleTemplate(_0x44030c[_0x541dbd(0x1a0)]||''),saveBatchFillerFlowTemplate(_0x44030c[_0x541dbd(0x190)]||''),saveAiTemplate(_0x44030c[_0x541dbd(0x190)]||'');else _0x44030c[_0x541dbd(0x180)]&&(saveBatchFillerRuleTemplate(''),saveBatchFillerFlowTemplate(_0x44030c[_0x541dbd(0x180)]||''),saveAiTemplate(_0x44030c[_0x541dbd(0x180)]||''));}log(_0x541dbd(0x13f),_0x541dbd(0x178)),toastr[_0x541dbd(0x178)](_0x541dbd(0x1f7),'设置成功'),typeof _0x5a1455==='function'&&_0x5a1455();}catch(_0x5dc607){log(_0x541dbd(0x200)+_0x5dc607[_0x541dbd(0x196)],'error'),toastr[_0x541dbd(0x191)](_0x541dbd(0x1c3)+_0x5dc607[_0x541dbd(0x196)],'错误');}},_0x420294[_0x55898a(0x117)](_0x1b23bf);},_0x1d0349[_0x5c1140(0x174)]();}
+const _0x5cf5ff=_0x8bba;(function(_0x5d0531,_0x138b26){const _0x171552=_0x8bba,_0x529a39=_0x5d0531();while(!![]){try{const _0x43e125=-parseInt(_0x171552(0x1f7))/0x1*(-parseInt(_0x171552(0x1fa))/0x2)+parseInt(_0x171552(0x2c9))/0x3*(-parseInt(_0x171552(0x270))/0x4)+-parseInt(_0x171552(0x1fb))/0x5+-parseInt(_0x171552(0x278))/0x6*(-parseInt(_0x171552(0x2b8))/0x7)+parseInt(_0x171552(0x266))/0x8*(parseInt(_0x171552(0x2ae))/0x9)+parseInt(_0x171552(0x20a))/0xa+-parseInt(_0x171552(0x21c))/0xb;if(_0x43e125===_0x138b26)break;else _0x529a39['push'](_0x529a39['shift']());}catch(_0x472f46){_0x529a39['push'](_0x529a39['shift']());}}}(_0x2ce6,0x6aa4a));import{getContext,extension_settings}from'/scripts/extensions.js';import{saveChat,saveSettingsDebounced}from'/script.js';import{log}from'./logger.js';import{fillWithSecondaryApi}from'./secondary-filler.js';import{getChatPiece,saveChatDebounced}from'../../utils/utils.js';import{extensionName}from'../../utils/settings.js';import{DEFAULT_AI_RULE_TEMPLATE,DEFAULT_AI_FLOW_TEMPLATE}from'./settings.js';import{renderTables}from'../../ui/table-bindings.js';import{updateOrInsertTableInChat}from'../../ui/message-table-renderer.js';const TABLE_DATA_KEY=_0x5cf5ff(0x26b);let currentTablesState=null,highlightedCells=new Set(),updatedTables=new Set();export function addHighlight(_0x3ab956,_0xe98281,_0x1ac017){const _0x293d13=_0x5cf5ff,_0x19b57d=_0x3ab956+'-'+_0xe98281+'-'+_0x1ac017;highlightedCells[_0x293d13(0x249)](_0x19b57d);}export function getHighlights(){return highlightedCells;}export function clearHighlights(){const _0x18b5a4=_0x5cf5ff;highlightedCells[_0x18b5a4(0x1e1)]>0x0&&(highlightedCells[_0x18b5a4(0x269)](),log(_0x18b5a4(0x205),'info'));}export function getUpdatedTables(){return updatedTables;}export function clearUpdatedTables(){const _0x3d8ec4=_0x5cf5ff;updatedTables[_0x3d8ec4(0x1e1)]>0x0&&(updatedTables[_0x3d8ec4(0x269)](),log(_0x3d8ec4(0x200),'info'));}export function setMemoryState(_0x2f0d1c){currentTablesState=_0x2f0d1c;}export function getMemoryState(){return currentTablesState;}const defaultTemplate={'tables':[{'name':_0x5cf5ff(0x211),'headers':['日期','时段','时间','地点',_0x5cf5ff(0x28f)],'note':'【核心作用】此表格用于精确追踪故事发生的即时时空背景,确保时间与空间的连续性。它应该始终只包含一行,代表当前的“镜头”位置。\x0a【字段详解】\x0a-\x20日期:\x20格式为\x27YYYY-MM-DD\x27。若日期未知,请根据上下文合理推断或设定一个初始日期,如\x27大夏3年-9月-10日\x27。\x0a-\x20时段:\x20严格遵循规定(凌晨:0-5时;早晨:5-8时;上午:8-11时;中午:11-13时;下午:13-16时;傍晚:16-19时;晚上:19-24时)。\x0a-\x20时间:\x20格式为\x27HH:MM\x27。若时间未知,可根据时段估算,如\x2708:30\x27。\x0a-\x20地点:\x20描述当前场景发生的具体位置,应尽可能精确,例如\x27XX街的咖啡馆\x27而非\x27城里\x27。\x0a-\x20此地角色:\x20列出当前场景中所有在场且参与互动的主要角色,用\x27/\x27分隔。','rule_add':_0x5cf5ff(0x25a),'rule_delete':_0x5cf5ff(0x2c7),'rule_update':_0x5cf5ff(0x26f),'charLimitRules':{},'rowLimitRule':0x1,'rows':[]},{'name':_0x5cf5ff(0x223),'headers':['角色名','外貌','身形','衣着','性格','身份','职业',_0x5cf5ff(0x286),'爱好','住所',_0x5cf5ff(0x293)],'note':'【核心作用】此表格是角色关系和状态的核心数据库,用于记录所有在故事中出现的重要角色的详细信息。\x0a【字段详解】\x0a-\x20角色名:\x20角色的唯一标识。\x0a-\x20外貌:\x20描述五官、发型、发色、肤色等面部特征。\x0a-\x20身形:\x20描述身高、体型、肌肉状况、特殊身体标记(如伤疤)等。\x0a-\x20衣着:\x20描述角色当前或标志性的穿着,包括服装、配饰等。\x0a-\x20性格:\x20概括角色的核心性格特质,使用1-3个关键词,如\x27勇敢/鲁莽/忠诚\x27。\x0a-\x20身份:\x20角色的社会背景或出身,如\x27贵族后裔\x27、\x27流浪者\x27。\x0a-\x20职业:\x20角色赖以谋生的工作或职责,如\x27佣兵\x27、\x27学者\x27。\x0a-\x20与关系:\x20描述该角色与主角之间的社会或情感关系,如\x27盟友\x27、\x27导师\x27、\x27敌人\x27。\x0a-\x20爱好:\x20角色的兴趣和消遣活动。\x0a-\x20住所:\x20角色的常住地。\x0a-\x20其他重要信息:\x20记录任何不属于以上类别但对角色至关重要的信息,如特殊能力、过去的经历等。','rule_add':_0x5cf5ff(0x2d1),'rule_delete':_0x5cf5ff(0x2d5),'rule_update':_0x5cf5ff(0x29a),'charLimitRules':{'10':0x1e},'rowLimitRule':0x0,'rows':[]},{'name':_0x5cf5ff(0x23f),'headers':['任务名','类型','详情','状态',_0x5cf5ff(0x2d7),'地点',_0x5cf5ff(0x224),'结果'],'note':_0x5cf5ff(0x27d),'rule_add':_0x5cf5ff(0x246),'rule_delete':_0x5cf5ff(0x2ab),'rule_update':_0x5cf5ff(0x2ca),'charLimitRules':{},'rowLimitRule':0xa,'rows':[]},{'name':_0x5cf5ff(0x23a),'headers':['物品名','类型','详情','状态',_0x5cf5ff(0x23d),_0x5cf5ff(0x238)],'note':_0x5cf5ff(0x203),'rule_add':_0x5cf5ff(0x2d3),'rule_delete':_0x5cf5ff(0x1e8),'rule_update':_0x5cf5ff(0x2b7),'charLimitRules':{},'rowLimitRule':0x0,'rows':[]},{'name':'技能栏','headers':[_0x5cf5ff(0x1dc),_0x5cf5ff(0x259)],'note':_0x5cf5ff(0x22c),'rule_add':_0x5cf5ff(0x288),'rule_delete':_0x5cf5ff(0x251),'rule_update':'【触发条件】当一个已知技能的效果发生进化、变异或被添加了新的限制/效果时(例如,技能升级),必须更新其“技能效果”描述。','charLimitRules':{},'rowLimitRule':0x0,'rows':[]},{'name':_0x5cf5ff(0x1fc),'headers':['类型','具体描述'],'note':'【核心作用】此表格记录了来自的、超越故事本身的“元指令”或世界观设定,拥有最高解释权。内容应被严格遵守,禁止AI自行修改。\x0a【字段详解】\x0a-\x20类型:\x20指令的分类,如\x27世界观设定\x27、\x27剧情走向要求\x27、\x27角色行为禁令\x27。\x0a-\x20具体描述:\x20完整、准确地记录提出的具体要求。','rule_add':_0x5cf5ff(0x28e),'rule_delete':'【触发条件】只能在明确表示要移除或废弃某条设定时,才能删除对应行。','rule_update':'【触发条件】只能在明确表示要修改某条设定时,才能更新对应行的描述。','charLimitRules':{},'rowLimitRule':0x0,'rows':[]}]};function _0x2ce6(){const _0x16998a=['新列\x20','message',')第(','result','below','readAsText','appendChild','重要原因','injectionFlowTemplate','物品栏','执行AI指令:\x20insertRow(tableIndex=','纯净预设','拥有者','全局预设已成功导入并保存到扩展设置中。','任务栏','名为\x20\x22','AI指令块为空,无需执行任何操作。','未能保存回退状态,操作中止。','未在聊天记录中找到表格,正在加载全局预设...','dispatchEvent','createElement','【触发条件】当以下情况发生时,应添加新行:\x0a1.\x20角色接下一个明确的、有目标的委托或命令。\x0a2.\x20角色们达成一个具体的、需要在未来执行的约定。\x0a3.\x20角色为自己设定一个长期的、关键性的目标。','\x20行已标记为待删除。','Amily2-','add','extra','正在尝试从第\x20','预设已成功导入并应用。','note','\x22\x20的表格已存在。','batch_filler_flow_template','在第\x20','【触发条件】如果发现表格中存在两个描述完全相同的重复技能,应删除其中一个。如果记录了非的技能,应立即删除。','aiTemplate','新表格状态已强制写入最新消息并立即保存。','完整备份','rule_update','聊天记录不足,无法执行回退操作。','trim','click','技能效果','【触发条件】当故事开始,且此表格为空时,必须立即根据初始场景创建第一行。',']\x20的顺序已调整。','\x20(索引\x20','chat',']\x20的规则已更新。','type','无法移动表格:索引\x20','插入行失败:找不到索引为\x20','全局预设已清除,新聊天将使用默认模板。','文件格式无效或缺少版本号/表格数据。','【清除全局预设】\x0a\x0a您确定要清除已设置的全局预设吗?\x0a\x0a清除后,新聊天将恢复使用扩展内置的默认表格模板。','amily2_ai_template','8MUezBP','导出成功','当前没有设置全局预设。','clear','所有表格的剧情内容已清空。','amily2_tables_data','操作完成',',\x20data=','执行失败','【触发条件】当以下任一情况发生时,必须更新此行:\x0a1.\x20时间发生显著跳跃(例如,\x27几小时后\x27、\x27第二天\x27)。\x0a2.\x20角色从一个地点移动到另一个地点。\x0a3.\x20场景中关键角色的出入导致在场人员发生变化。','4ifrMtI','\x20条表格操作指令...','rowIndex,','href','表格名称不能为空。','加载全局预设失败:\x20','【修改】:\x20','map','3462024nSnblV','重命名失败:名称不能为空。',',\x20rowIndex=',')超出规定(','Amily2-Table-Preset-v2.0-full','【核心作用】追踪故事中的主要情节线、目标和挑战。只记录对剧情发展有重大影响的“任务”,忽略日常琐事。\x0a【字段详解】\x0a-\x20任务名:\x20任务的简洁概括,如\x27寻找失落的神器\x27。\x0a-\x20类型:\x20任务的分类,如\x27主线\x27、\x27支线\x27、\x27个人\x27、\x27约定\x27。\x0a-\x20详情:\x20对任务目标和背景的简要描述。\x0a-\x20状态:\x20任务的当前进展,如\x27未开始\x27、\x27进行中\x27、\x27已完成\x27、\x27已失败\x27、\x27已取消\x27。\x0a-\x20执行者:\x20负责完成此任务的角色名。\x0a-\x20地点:\x20任务关键环节发生的地点。\x0a-\x20开始时间/结束时间:\x20记录任务的起止时间,格式\x27YYYY-MM-DD\x27,若未结束则结束时间留空。\x0a-\x20结果:\x20任务完成或失败后的最终结果。','AI\x20指令更新了表格\x20[','global_table_preset','导入成功','已提交并永久删除了\x20','(该表当前内容为空)\x0a','执行AI指令时发生错误:\x20',']\x20末尾新增一行。','removeChild','与关系','columnWidths','【触发条件】当在故事中首次成功施展或习得一个全新的、表格中未记录的技能时,必须添加。','移动。','操作成功','charLimitRule','Amily2-Table-Preset-v2.0-clean','”已更新为“','【触发条件】当通过括号、旁白或其他明确的“第四面墙”方式,提出关于故事背景、规则或未来走向的指令时,必须记录于此。','此地角色','stringify','getPrototypeOf','无法回退:聊天记录不足。','其他重要信息','rule_add','\x20条消息加载表格状态...','导入操作已取消。','表格不存在。','toString',']\x20已被成功废黜。','【触发条件】当角色的任何信息发生持久性或关键性变化时,必须更新对应单元格。例如:\x0a1.\x20外貌/身形/衣着发生永久性改变(如断肢、换上新装备)。\x0a2.\x20性格因重大事件而扭转。\x0a3.\x20身份或职业发生变更(如继承王位、被解雇)。\x0a4.\x20与的关系发生根本性转变(如从敌人变为盟友)。','columnIndex','\x20中操作。','缺少状态或目标消息,无法保存。','batchFillerRuleTemplate','headers','”已向','【说明】:\x0a','表格\x20[','\x20列。',')行以下,但切莫完全删除。】','没有可导出的表格数据。','所有AI指令已成功执行完毕。','target',']\x20新增了一列。','mes','function','【触发条件】当任务列表超过10行时,优先删除最早的、已经“已完成”且与当前剧情关联度最低的任务。如果存在内容完全重复的任务,应删除。','length','未能在上一楼找到可用的表格状态。','4724739caHdOH','成功将表格\x20','清空行数据后的状态已强制写入最新消息并立即保存。','files','\x0a*\x20','已成功将回退后的状态保存至最新消息。','无法导出:当前表格状态为空。','body',']\x20新增了一行。','【触发条件】当物品的“状态”(如被损坏)、“拥有者”(如被转交或被盗)或“详情”(如发现了新功能)发生变化时,必须更新。','7hzQNPf',']\x20在第\x20','执行AI指令:\x20updateRow(tableIndex=','UI已更新以显示回退后的状态。','无法找到可锚定的消息或保存失败,顺序调整可能不会被持久化!','replace','onload','file','\x20条消息中找到基准表格数据。','这是一个新创建的表格。','aiFlowTemplate','split','\x0a---\x0a','执行AI指令时出错:\x20','重命名失败','【触发条件】任何时候,如果此表格的行数超过一行,必须删除旧的行,只保留最新、最准确的一行。','charLimitRules','2453931pdnECt','【触发条件】当任务的“状态”发生任何变化时,必须更新。例如,从\x27进行中\x27变为\x27已完成\x27。当任务的“详情”或“结果”有新的关键信息补充时,也应更新。','batchFillerFlowTemplate','version','表格\x20\x22','重新填表失败:\x20','未知操作','\x20的列。','【触发条件】当一个有名有姓的角色首次出现,并与或当前剧情发生有意义的互动时,必须为其创建新的一行。','\x22\x20已重命名为\x20\x22','【触发条件】当一个物品被明确赋予了特殊意义(如被赠予、在关键事件中扮演重要角色)或展示出独特功能时,应为其创建条目。','isArray','【触发条件】当一个角色被确认永久性死亡(非假死或失踪),且其存在不再对后续剧情有直接影响时,可以删除该行。','表格顺序调整后的状态已强制写入最新消息并立即保存。','执行者','fill','warn','\x20行移动到第\x20','success','filter','batch_filler_rule_template','above','parse','成功删除了表格\x20','执行AI指令:\x20deleteRow(tableIndex=','所有表格的行数据已在内存中清空。','废黜表格后的状态已强制写入最新消息并立即保存。','技能名','状态回退成功,准备重新填表...','object','error','\x22\x20已更新内存状态。','size','\x20已在边界。','some',')列,字符超出规定(','\x20的表格。','join','未在AI返回内容中找到有效的\x20\x20指令块。','【触发条件】当一个物品被彻底摧毁、消耗完毕或永久失去其特殊意义时,可以删除。','download','every','left','.json','AI返回内容为空,无法更新表格。','回退状态保存失败,操作中止。','准备执行从AI返回的\x20','导入的预设已强制写入最新消息并立即保存。','rows','aiRuleTemplate','rule_delete','match','无法找到可锚定的消息或保存失败,清空操作可能不会被持久化!','input','46285PrBWdv','tables',')行(','26svHneE','393665RJGexp','设定栏','\x20行位置插入了新行。','forEach',']\x20的第\x20','已清除所有表格的更新标记。','导入的表格数据格式不正确:\x20','用户取消了清除全局预设的操作。','【核心作用】记录那些在故事中具有特殊功能、背景或情感价值的关键物品。普通物品不应记录。\x0a【字段详解】\x0a-\x20物品名:\x20物品的名称。\x0a-\x20类型:\x20物品的分类,如\x27武器\x27、\x27道具\x27、\x27信物\x27、\x27关键物品\x27。\x0a-\x20详情:\x20描述物品的外观、材质和已知功能。\x0a-\x20状态:\x20物品的当前状况,如\x27完好\x27、\x27破损\x27、\x27能量耗尽\x27。\x0a-\x20拥有者:\x20当前持有该物品的角色名。\x0a-\x20重要原因:\x20解释该物品为何重要,例如\x27是解开谜题的钥匙\x27或\x27是母亲的遗物\x27。','删除列失败:在表格\x20','已清除所有单元格高亮标记。','AI指令意图更新不存在的行\x20(rowIndex:\x20','runner','toISOString','limit','5829960qJeaWr','插入了新列。','pending-deletion','导入失败:','全局预设已被清除。','无需清除,当前未设置任何全局预设。','normal','时空栏','onchange','\x0a\x20\x20\x20\x20\x20\x20\x20\x20','\x20行。','application/json','创建失败','number','...]','rowLimitRule','Amily2-Table-Preset-v3.0-separated_templates','AI指令错误:尝试在不存在的表格索引\x20','10484716LusrZX','操作已取消。','constructor','splice','push','\x20行已恢复。','confirm','角色栏','开始时间/结束时间','createObjectURL','rowStatuses','无法找到可锚定的消息或保存失败,新表格可能不会被持久化!','】已开始下载。','回退重填过程中发生错误:\x20','slice','用户取消了全局预设导入操作。','【核心作用】专门用于记录主角掌握的各种技能、魔法、被动能力或特殊专长。\x0a【字段详解】\x0a-\x20技能名:\x20技能的正式名称。\x0a-\x20技能效果:\x20清晰、简洁地描述该技能使用时产生的具体效果、消耗和限制条件。','revokeObjectURL','【删除】:\x20','name','info'];_0x2ce6=function(){return _0x16998a;};return _0x2ce6();}function getDefaultTables(){const _0x34c537=_0x5cf5ff;log('从预设模板生成默认表格...',_0x34c537(0x230));const _0x430d2a=JSON[_0x34c537(0x2df)](JSON[_0x34c537(0x290)](defaultTemplate[_0x34c537(0x1f8)]));return _0x430d2a['forEach'](_0x13e39c=>{const _0x5e72bd=_0x34c537;_0x13e39c['charLimitRule']={'columnIndex':-0x1,'limit':0x0},_0x13e39c['rowLimitRule']=0x0,_0x13e39c[_0x5e72bd(0x287)]=[];}),_0x430d2a;}export function loadTables(_0x39b312=-0x1){const _0x1bf0b7=_0x5cf5ff,_0xc82263=getContext();if(_0xc82263&&_0xc82263[_0x1bf0b7(0x25d)]&&_0xc82263[_0x1bf0b7(0x25d)]['length']>0x0){const _0x422576=_0x39b312===-0x1?_0xc82263[_0x1bf0b7(0x25d)][_0x1bf0b7(0x2ac)]-0x1:_0x39b312-0x1;for(let _0x1d307a=_0x422576;_0x1d307a>=0x0;_0x1d307a--){const _0x25c6f2=_0xc82263[_0x1bf0b7(0x25d)][_0x1d307a];if(_0x25c6f2[_0x1bf0b7(0x24a)]&&_0x25c6f2[_0x1bf0b7(0x24a)][TABLE_DATA_KEY]){log(_0x1bf0b7(0x250)+_0x1d307a+_0x1bf0b7(0x2c0),'info');let _0x574b07=JSON[_0x1bf0b7(0x2df)](JSON[_0x1bf0b7(0x290)](_0x25c6f2['extra'][TABLE_DATA_KEY]));return _0x574b07[_0x1bf0b7(0x1fe)](_0xbdff8c=>{const _0x30b150=_0x1bf0b7;if(_0xbdff8c['note']===undefined)_0xbdff8c[_0x30b150(0x24d)]='无';if(_0xbdff8c[_0x30b150(0x294)]===undefined)_0xbdff8c[_0x30b150(0x294)]='允许';if(_0xbdff8c[_0x30b150(0x1f3)]===undefined)_0xbdff8c[_0x30b150(0x1f3)]='允许';if(_0xbdff8c[_0x30b150(0x255)]===undefined)_0xbdff8c[_0x30b150(0x255)]='允许';_0xbdff8c[_0x30b150(0x28b)]&&!_0xbdff8c[_0x30b150(0x2c8)]&&(_0xbdff8c['charLimitRules']={},_0xbdff8c[_0x30b150(0x28b)][_0x30b150(0x29b)]!==-0x1&&_0xbdff8c['charLimitRule']['limit']>0x0&&(_0xbdff8c['charLimitRules'][_0xbdff8c[_0x30b150(0x28b)][_0x30b150(0x29b)]]=_0xbdff8c['charLimitRule'][_0x30b150(0x209)]));delete _0xbdff8c[_0x30b150(0x28b)];if(_0xbdff8c[_0x30b150(0x219)]===undefined)_0xbdff8c[_0x30b150(0x219)]=0x0;if(_0xbdff8c[_0x30b150(0x287)]===undefined)_0xbdff8c[_0x30b150(0x287)]=[];!_0xbdff8c[_0x30b150(0x226)]&&(_0xbdff8c[_0x30b150(0x226)]=Array(_0xbdff8c[_0x30b150(0x1f1)][_0x30b150(0x2ac)])['fill'](_0x30b150(0x210)));}),currentTablesState=_0x574b07,currentTablesState;}}}if(extension_settings[extensionName]?.[_0x1bf0b7(0x27f)]){log(_0x1bf0b7(0x243),'info');try{const _0x495caf=extension_settings[extensionName]['global_table_preset'];return currentTablesState=JSON[_0x1bf0b7(0x2df)](JSON['stringify'](_0x495caf[_0x1bf0b7(0x1f8)])),_0x495caf[_0x1bf0b7(0x29e)]!==undefined&&saveBatchFillerRuleTemplate(_0x495caf[_0x1bf0b7(0x29e)]),_0x495caf[_0x1bf0b7(0x2cb)]!==undefined&&saveBatchFillerFlowTemplate(_0x495caf['batchFillerFlowTemplate']),currentTablesState;}catch(_0x265c56){log(_0x1bf0b7(0x275)+_0x265c56['message'],_0x1bf0b7(0x1df));}}return log('未找到任何表格数据或全局预设,使用默认模板。','info'),currentTablesState=getDefaultTables(),currentTablesState;}export function saveStateToMessage(_0x43faad,_0x8a3cf6){const _0x4b3dd1=_0x5cf5ff;if(!_0x43faad||!_0x8a3cf6)return log(_0x4b3dd1(0x29d),'error'),![];return!_0x8a3cf6[_0x4b3dd1(0x24a)]&&(_0x8a3cf6[_0x4b3dd1(0x24a)]={}),_0x8a3cf6[_0x4b3dd1(0x24a)][TABLE_DATA_KEY]=JSON[_0x4b3dd1(0x2df)](JSON[_0x4b3dd1(0x290)](_0x43faad)),log('表格状态已准备写入消息\x20['+_0x8a3cf6[_0x4b3dd1(0x2a9)]['substring'](0x0,0x14)+_0x4b3dd1(0x218),_0x4b3dd1(0x230)),!![];}export function saveTables(_0xd0fa2a=_0x5cf5ff(0x2cf)){const _0x5a7e23=_0x5cf5ff;return log('UI操作\x20\x22'+_0xd0fa2a+_0x5a7e23(0x1e0),'info'),!![];}export function deleteColumn(_0x5cfef1,_0x400b4b){const _0x1596e4=_0x5cf5ff,_0x168183=getMemoryState();if(!_0x168183[_0x5cfef1]||_0x400b4b<0x0||_0x400b4b>=_0x168183[_0x5cfef1][_0x1596e4(0x29f)][_0x1596e4(0x2ac)]){log(_0x1596e4(0x204)+_0x5cfef1+'\x20中找不到索引为\x20'+_0x400b4b+_0x1596e4(0x2d0),_0x1596e4(0x1df));return;}_0x168183[_0x5cfef1][_0x1596e4(0x29f)]['splice'](_0x400b4b,0x1),_0x168183[_0x5cfef1][_0x1596e4(0x1f1)][_0x1596e4(0x1fe)](_0x17d884=>{const _0x49a3fd=_0x1596e4;_0x17d884[_0x49a3fd(0x2ac)]>_0x400b4b&&_0x17d884[_0x49a3fd(0x21f)](_0x400b4b,0x1);}),_0x168183[_0x5cfef1][_0x1596e4(0x287)]&&_0x168183[_0x5cfef1][_0x1596e4(0x287)][_0x1596e4(0x2ac)]>_0x400b4b&&_0x168183[_0x5cfef1][_0x1596e4(0x287)][_0x1596e4(0x21f)](_0x400b4b,0x1),log(_0x1596e4(0x2e0)+_0x5cfef1+'\x20的第\x20'+(_0x400b4b+0x1)+_0x1596e4(0x2a3),_0x1596e4(0x2db)),saveTables(_0x168183);}export function moveRow(_0x27fd43,_0x3d87b9,_0x435c2d){const _0x550651=_0x5cf5ff,_0x49b26a=getMemoryState(),_0x7053cf=_0x49b26a[_0x27fd43];if(!_0x7053cf||_0x3d87b9<0x0||_0x3d87b9>=_0x7053cf[_0x550651(0x1f1)][_0x550651(0x2ac)])return;const _0x47c421=_0x435c2d==='up'?_0x3d87b9-0x1:_0x3d87b9+0x1;if(_0x47c421<0x0||_0x47c421>=_0x7053cf[_0x550651(0x1f1)]['length'])return;const [_0x55b71f]=_0x7053cf[_0x550651(0x1f1)][_0x550651(0x21f)](_0x3d87b9,0x1);_0x7053cf[_0x550651(0x1f1)][_0x550651(0x21f)](_0x47c421,0x0,_0x55b71f);if(_0x7053cf[_0x550651(0x226)]&&_0x7053cf['rowStatuses']['length']===_0x7053cf[_0x550651(0x1f1)][_0x550651(0x2ac)]+0x1){const [_0x1dcec7]=_0x7053cf['rowStatuses'][_0x550651(0x21f)](_0x3d87b9,0x1);_0x7053cf[_0x550651(0x226)][_0x550651(0x21f)](_0x47c421,0x0,_0x1dcec7);}log(_0x550651(0x2af)+_0x27fd43+'\x20的第\x20'+(_0x3d87b9+0x1)+_0x550651(0x2da)+(_0x47c421+0x1)+_0x550651(0x214),_0x550651(0x2db)),saveTables(_0x49b26a);}export function insertRow(_0x2c4fb5,_0x5438c7,_0x3a0c2b=_0x5cf5ff(0x235)){const _0x600e4c=_0x5cf5ff,_0x5c094b=getMemoryState(),_0x53a8b6=_0x5c094b[_0x2c4fb5];if(!_0x53a8b6){log(_0x600e4c(0x261)+_0x2c4fb5+_0x600e4c(0x1e5),'error');return;}let _0x40c8ad;typeof _0x5438c7===_0x600e4c(0x217)?_0x40c8ad=_0x3a0c2b===_0x600e4c(0x2de)?_0x5438c7:_0x5438c7+0x1:_0x40c8ad=_0x53a8b6[_0x600e4c(0x1f1)][_0x600e4c(0x2ac)];if(_0x40c8ad<0x0)_0x40c8ad=0x0;if(_0x40c8ad>_0x53a8b6[_0x600e4c(0x1f1)][_0x600e4c(0x2ac)])_0x40c8ad=_0x53a8b6[_0x600e4c(0x1f1)][_0x600e4c(0x2ac)];const _0x5e7d6f=new Array(_0x53a8b6[_0x600e4c(0x29f)]['length'])[_0x600e4c(0x2d8)]('');if(typeof _0x5438c7===_0x600e4c(0x1de)&&_0x5438c7!==null)for(const _0x393aba in _0x5438c7){const _0x318faf=parseInt(_0x393aba,0xa);!isNaN(_0x318faf)&&_0x318faf<_0x5e7d6f[_0x600e4c(0x2ac)]&&(_0x5e7d6f[_0x318faf]=_0x5438c7[_0x393aba],addHighlight(_0x2c4fb5,_0x40c8ad,_0x318faf));}_0x53a8b6['rows'][_0x600e4c(0x21f)](_0x40c8ad,0x0,_0x5e7d6f);if(!_0x53a8b6[_0x600e4c(0x226)])_0x53a8b6[_0x600e4c(0x226)]=Array(_0x53a8b6[_0x600e4c(0x1f1)][_0x600e4c(0x2ac)])['fill'](_0x600e4c(0x210));_0x53a8b6[_0x600e4c(0x226)][_0x600e4c(0x21f)](_0x40c8ad,0x0,_0x600e4c(0x210)),updatedTables['add'](_0x2c4fb5),log('成功在表格\x20'+_0x53a8b6[_0x600e4c(0x22f)]+_0x600e4c(0x25c)+_0x2c4fb5+')\x20的第\x20'+(_0x40c8ad+0x1)+_0x600e4c(0x1fd),_0x600e4c(0x2db));const _0x5e236c=getContext();if(_0x5e236c[_0x600e4c(0x25d)]&&_0x5e236c[_0x600e4c(0x25d)][_0x600e4c(0x2ac)]>0x0){const _0x33ada6=_0x5e236c[_0x600e4c(0x25d)][_0x5e236c[_0x600e4c(0x25d)][_0x600e4c(0x2ac)]-0x1];if(saveStateToMessage(_0x5c094b,_0x33ada6)){saveChat();return;}}saveChatDebounced();}export function addRow(_0x580950){const _0xc24c1e=_0x5cf5ff;if(!currentTablesState||!currentTablesState[_0x580950])return;const _0x5cbf4d=currentTablesState[_0x580950],_0x4b7789=_0x5cbf4d[_0xc24c1e(0x29f)][_0xc24c1e(0x2ac)],_0xc142b7=Array(_0x4b7789)[_0xc24c1e(0x2d8)]('');_0x5cbf4d[_0xc24c1e(0x1f1)][_0xc24c1e(0x220)](_0xc142b7);if(!_0x5cbf4d[_0xc24c1e(0x226)])_0x5cbf4d['rowStatuses']=Array(_0x5cbf4d[_0xc24c1e(0x1f1)][_0xc24c1e(0x2ac)])[_0xc24c1e(0x2d8)]('normal');_0x5cbf4d[_0xc24c1e(0x226)][_0xc24c1e(0x220)]('normal'),updatedTables[_0xc24c1e(0x249)](_0x580950);const _0x5887dd='表格\x20['+_0x5cbf4d[_0xc24c1e(0x22f)]+_0xc24c1e(0x2b6);log(_0x5887dd,_0xc24c1e(0x230));const _0x4f37d9=getContext();if(_0x4f37d9[_0xc24c1e(0x25d)]&&_0x4f37d9[_0xc24c1e(0x25d)]['length']>0x0){const _0x2e1dc2=_0x4f37d9['chat'][_0x4f37d9[_0xc24c1e(0x25d)][_0xc24c1e(0x2ac)]-0x1];if(saveStateToMessage(currentTablesState,_0x2e1dc2)){saveChat();return;}}saveChatDebounced();}export function addColumn(_0x23ac72){const _0x4eedb8=_0x5cf5ff;if(!currentTablesState||!currentTablesState[_0x23ac72])return;const _0x242c25=currentTablesState[_0x23ac72],_0x3c975a=_0x4eedb8(0x231)+(_0x242c25[_0x4eedb8(0x29f)][_0x4eedb8(0x2ac)]+0x1);_0x242c25['headers'][_0x4eedb8(0x220)](_0x3c975a),_0x242c25[_0x4eedb8(0x1f1)][_0x4eedb8(0x1fe)](_0x3c41d9=>_0x3c41d9[_0x4eedb8(0x220)](''));if(!_0x242c25[_0x4eedb8(0x287)])_0x242c25[_0x4eedb8(0x287)]=[];_0x242c25[_0x4eedb8(0x287)][_0x4eedb8(0x220)](null);const _0x14acaa=_0x4eedb8(0x2a2)+_0x242c25[_0x4eedb8(0x22f)]+_0x4eedb8(0x2a8);log(_0x14acaa,'info');const _0xa7916=getContext();if(_0xa7916[_0x4eedb8(0x25d)]&&_0xa7916['chat']['length']>0x0){const _0x164454=_0xa7916[_0x4eedb8(0x25d)][_0xa7916[_0x4eedb8(0x25d)][_0x4eedb8(0x2ac)]-0x1];if(saveStateToMessage(currentTablesState,_0x164454)){saveChat();return;}}saveChatDebounced();}export function updateHeader(_0x43b31d,_0x39914e,_0x493fe5){const _0x20f60f=_0x5cf5ff;if(!currentTablesState||!currentTablesState[_0x43b31d]||currentTablesState[_0x43b31d][_0x20f60f(0x29f)][_0x39914e]===undefined)return;const _0x4fc9ff=currentTablesState[_0x43b31d][_0x20f60f(0x22f)],_0x4f74f9=currentTablesState[_0x43b31d][_0x20f60f(0x29f)][_0x39914e];currentTablesState[_0x43b31d][_0x20f60f(0x29f)][_0x39914e]=_0x493fe5;const _0x46af9f='表格\x20['+_0x4fc9ff+']\x20的表头“'+_0x4f74f9+_0x20f60f(0x28d)+_0x493fe5+'”。';log(_0x46af9f,_0x20f60f(0x230));const _0x312619=getContext();if(_0x312619[_0x20f60f(0x25d)]&&_0x312619['chat'][_0x20f60f(0x2ac)]>0x0){const _0x36a4c6=_0x312619['chat'][_0x312619['chat']['length']-0x1];if(saveStateToMessage(currentTablesState,_0x36a4c6)){saveChat();return;}}saveChatDebounced();}export async function deleteRow(_0x3410bd,_0x17ed90){const _0x4c194c=_0x5cf5ff,_0x3115c2=currentTablesState?.[_0x3410bd];if(!_0x3115c2||!_0x3115c2[_0x4c194c(0x1f1)][_0x17ed90])return;!_0x3115c2['rowStatuses']&&(_0x3115c2[_0x4c194c(0x226)]=Array(_0x3115c2['rows'][_0x4c194c(0x2ac)])[_0x4c194c(0x2d8)](_0x4c194c(0x210)));_0x3115c2[_0x4c194c(0x226)][_0x17ed90]=_0x4c194c(0x20c),updatedTables['add'](_0x3410bd);const _0x39aef0='表格\x20['+_0x3115c2[_0x4c194c(0x22f)]+']\x20的第\x20'+(_0x17ed90+0x1)+_0x4c194c(0x247);log(_0x39aef0,_0x4c194c(0x230));const _0xa4a1b8=getContext();if(_0xa4a1b8['chat']?.[_0x4c194c(0x2ac)]>0x0){const _0x21a04c=_0xa4a1b8[_0x4c194c(0x25d)][_0xa4a1b8[_0x4c194c(0x25d)][_0x4c194c(0x2ac)]-0x1];if(saveStateToMessage(currentTablesState,_0x21a04c)){await saveChat(),renderTables();return;}}await saveChatDebounced(),renderTables();}export async function restoreRow(_0x47866a,_0x294ccd){const _0x54cd13=_0x5cf5ff,_0x337c1c=currentTablesState?.[_0x47866a];if(!_0x337c1c||!_0x337c1c[_0x54cd13(0x1f1)][_0x294ccd]||!_0x337c1c['rowStatuses'])return;_0x337c1c[_0x54cd13(0x226)][_0x294ccd]=_0x54cd13(0x210),updatedTables[_0x54cd13(0x249)](_0x47866a);const _0x549fa4=_0x54cd13(0x2a2)+_0x337c1c['name']+']\x20的第\x20'+(_0x294ccd+0x1)+_0x54cd13(0x221);log(_0x549fa4,_0x54cd13(0x230));const _0x2e6d96=getContext();if(_0x2e6d96['chat']?.[_0x54cd13(0x2ac)]>0x0){const _0x489e79=_0x2e6d96['chat'][_0x2e6d96[_0x54cd13(0x25d)]['length']-0x1];if(saveStateToMessage(currentTablesState,_0x489e79)){await saveChat(),renderTables();return;}}await saveChatDebounced(),renderTables();}export function commitPendingDeletions(){const _0x5385fb=_0x5cf5ff;if(!currentTablesState)return![];let _0x12a0a8=0x0;currentTablesState['forEach']((_0x44e24c,_0x3405f7)=>{const _0x2193cf=_0x8bba;if(!_0x44e24c[_0x2193cf(0x226)]||_0x44e24c[_0x2193cf(0x226)][_0x2193cf(0x2ac)]===0x0)return;let _0x38e493=![];for(let _0xc66ef6=_0x44e24c[_0x2193cf(0x1f1)]['length']-0x1;_0xc66ef6>=0x0;_0xc66ef6--){_0x44e24c[_0x2193cf(0x226)][_0xc66ef6]===_0x2193cf(0x20c)&&(_0x44e24c['rows'][_0x2193cf(0x21f)](_0xc66ef6,0x1),_0x44e24c[_0x2193cf(0x226)][_0x2193cf(0x21f)](_0xc66ef6,0x1),_0x12a0a8++,_0x38e493=!![]);}_0x38e493&&updatedTables['add'](_0x3405f7);});if(_0x12a0a8>0x0)return log(_0x5385fb(0x281)+_0x12a0a8+_0x5385fb(0x214),'info'),!![];return![];}export function insertColumn(_0x1be27c,_0x40dfd3,_0xa1a59){const _0x5f5af7=_0x5cf5ff;if(!currentTablesState||!currentTablesState[_0x1be27c])return;const _0x1f7c85=currentTablesState[_0x1be27c],_0x3bcffb=_0xa1a59==='left'?_0x40dfd3:_0x40dfd3+0x1,_0x2b69dc='新列';_0x1f7c85[_0x5f5af7(0x29f)][_0x5f5af7(0x21f)](_0x3bcffb,0x0,_0x2b69dc),_0x1f7c85[_0x5f5af7(0x1f1)]['forEach'](_0x11a114=>_0x11a114[_0x5f5af7(0x21f)](_0x3bcffb,0x0,''));if(!_0x1f7c85[_0x5f5af7(0x287)])_0x1f7c85[_0x5f5af7(0x287)]=[];_0x1f7c85[_0x5f5af7(0x287)]['splice'](_0x3bcffb,0x0,null);const _0xb5cb6e='表格\x20['+_0x1f7c85[_0x5f5af7(0x22f)]+_0x5f5af7(0x2b9)+(_0x40dfd3+0x1)+'\x20列的'+(_0xa1a59===_0x5f5af7(0x1eb)?'左侧':'右侧')+_0x5f5af7(0x20b);log(_0xb5cb6e,_0x5f5af7(0x230));const _0x6a724d=getContext();if(_0x6a724d[_0x5f5af7(0x25d)]&&_0x6a724d['chat'][_0x5f5af7(0x2ac)]>0x0){const _0x4ddd86=_0x6a724d[_0x5f5af7(0x25d)][_0x6a724d['chat'][_0x5f5af7(0x2ac)]-0x1];if(saveStateToMessage(currentTablesState,_0x4ddd86)){saveChat();return;}}saveChatDebounced();}export function moveColumn(_0x79cc16,_0x1a188a,_0x15df15){const _0x400297=_0x5cf5ff;if(!currentTablesState||!currentTablesState[_0x79cc16])return;const _0x35e514=currentTablesState[_0x79cc16],_0x55355e=_0x35e514[_0x400297(0x29f)],_0x1ab8f0=_0x35e514[_0x400297(0x1f1)],_0x595228=_0x15df15==='left'?_0x1a188a-0x1:_0x1a188a+0x1;if(_0x595228<0x0||_0x595228>=_0x55355e['length']){log('无法移动列:索引\x20'+_0x1a188a+_0x400297(0x1e2),_0x400297(0x2d9));return;}const [_0x4a5148]=_0x55355e[_0x400297(0x21f)](_0x1a188a,0x1);_0x55355e['splice'](_0x595228,0x0,_0x4a5148),_0x1ab8f0[_0x400297(0x1fe)](_0x4e6fbd=>{const _0x425a2f=_0x400297,[_0xa4239d]=_0x4e6fbd[_0x425a2f(0x21f)](_0x1a188a,0x1);_0x4e6fbd['splice'](_0x595228,0x0,_0xa4239d);});if(_0x35e514[_0x400297(0x287)]&&_0x35e514[_0x400297(0x287)]['length']>_0x1a188a){const [_0xfd4a6b]=_0x35e514['columnWidths'][_0x400297(0x21f)](_0x1a188a,0x1);_0x35e514[_0x400297(0x287)][_0x400297(0x21f)](_0x595228,0x0,_0xfd4a6b);}const _0x3d4292=_0x400297(0x2a2)+_0x35e514['name']+']\x20的列“'+_0x4a5148+_0x400297(0x2a0)+(_0x15df15===_0x400297(0x1eb)?'左':'右')+_0x400297(0x289);log(_0x3d4292,'info');const _0x30d2ba=getContext();if(_0x30d2ba[_0x400297(0x25d)]&&_0x30d2ba[_0x400297(0x25d)][_0x400297(0x2ac)]>0x0){const _0x255ea4=_0x30d2ba[_0x400297(0x25d)][_0x30d2ba[_0x400297(0x25d)][_0x400297(0x2ac)]-0x1];if(saveStateToMessage(currentTablesState,_0x255ea4)){saveChat();return;}}saveChatDebounced();}export function deleteTable(_0x735e57){const _0xe42acf=_0x5cf5ff;if(!currentTablesState||!currentTablesState[_0x735e57])return;const _0x213081=currentTablesState[_0x735e57][_0xe42acf(0x22f)];currentTablesState[_0xe42acf(0x21f)](_0x735e57,0x1);const _0x3da7ce=_0xe42acf(0x2a2)+_0x213081+_0xe42acf(0x299);log(_0x3da7ce,_0xe42acf(0x2db));const _0x2359e1=getContext();if(_0x2359e1[_0xe42acf(0x25d)]&&_0x2359e1[_0xe42acf(0x25d)][_0xe42acf(0x2ac)]>0x0){const _0x5b0409=_0x2359e1[_0xe42acf(0x25d)][_0x2359e1[_0xe42acf(0x25d)][_0xe42acf(0x2ac)]-0x1];if(saveStateToMessage(currentTablesState,_0x5b0409)){saveChat(),log(_0xe42acf(0x1db),'success');return;}}log('无法找到可锚定的消息或保存失败,删除操作可能不会被持久化!',_0xe42acf(0x1df)),saveChatDebounced();}export function addTable(_0x571cd2){const _0x4fc2d7=_0x5cf5ff;if(!_0x571cd2||!_0x571cd2[_0x4fc2d7(0x257)]()){log('无法创建表格:名称不能为空。',_0x4fc2d7(0x1df)),toastr[_0x4fc2d7(0x1df)](_0x4fc2d7(0x274),_0x4fc2d7(0x216));return;}!currentTablesState&&loadTables();if(currentTablesState[_0x4fc2d7(0x1e3)](_0x11e6ff=>_0x11e6ff[_0x4fc2d7(0x22f)]===_0x571cd2['trim']())){log('无法创建表格:名为\x20\x22'+_0x571cd2+'\x22\x20的表格已存在。',_0x4fc2d7(0x1df)),toastr[_0x4fc2d7(0x1df)]('名为\x20\x22'+_0x571cd2+'\x22\x20的表格已存在。',_0x4fc2d7(0x216));return;}const _0x60604d={'name':_0x571cd2['trim'](),'headers':['新列\x201'],'rows':[],'rowStatuses':[],'columnWidths':[],'note':_0x4fc2d7(0x2c1),'rule_add':'允许','rule_delete':'允许','rule_update':'允许','charLimitRules':{},'rowLimitRule':0x0};currentTablesState[_0x4fc2d7(0x220)](_0x60604d);const _0x19f2c8='已成功创建新表格:['+_0x571cd2['trim']()+']。';log(_0x19f2c8,'success');const _0x22cf51=getContext();if(_0x22cf51[_0x4fc2d7(0x25d)]&&_0x22cf51['chat'][_0x4fc2d7(0x2ac)]>0x0){const _0x20b0b5=_0x22cf51[_0x4fc2d7(0x25d)][_0x22cf51['chat'][_0x4fc2d7(0x2ac)]-0x1];if(saveStateToMessage(currentTablesState,_0x20b0b5)){saveChat(),log(_0x4fc2d7(0x253),_0x4fc2d7(0x2db));return;}}log(_0x4fc2d7(0x227),_0x4fc2d7(0x1df)),saveChatDebounced();}export function renameTable(_0xd17636,_0x4a7b7f){const _0x2614c2=_0x5cf5ff;if(!currentTablesState||!currentTablesState[_0xd17636]){log('重命名失败:表格不存在。',_0x2614c2(0x1df)),toastr[_0x2614c2(0x1df)](_0x2614c2(0x297),'重命名失败');return;}const _0x27c58c=_0x4a7b7f[_0x2614c2(0x257)]();if(!_0x27c58c){log(_0x2614c2(0x279),_0x2614c2(0x1df)),toastr[_0x2614c2(0x1df)](_0x2614c2(0x274),_0x2614c2(0x2c6));return;}if(currentTablesState[_0x2614c2(0x1e3)]((_0x2addb3,_0x107806)=>_0x107806!==_0xd17636&&_0x2addb3[_0x2614c2(0x22f)]===_0x27c58c)){log('重命名失败:名为\x20\x22'+_0x27c58c+_0x2614c2(0x24e),_0x2614c2(0x1df)),toastr[_0x2614c2(0x1df)](_0x2614c2(0x240)+_0x27c58c+_0x2614c2(0x24e),'重命名失败');return;}const _0x3b811a=currentTablesState[_0xd17636][_0x2614c2(0x22f)];currentTablesState[_0xd17636]['name']=_0x27c58c,log(_0x2614c2(0x2cd)+_0x3b811a+_0x2614c2(0x2d2)+_0x27c58c+'\x22。','success');const _0x1f8d69=getContext();if(_0x1f8d69[_0x2614c2(0x25d)]&&_0x1f8d69['chat']['length']>0x0){const _0x3e8a75=_0x1f8d69[_0x2614c2(0x25d)][_0x1f8d69[_0x2614c2(0x25d)][_0x2614c2(0x2ac)]-0x1];if(saveStateToMessage(currentTablesState,_0x3e8a75)){saveChat();return;}}saveChatDebounced();}export function moveTable(_0x451a60,_0x3c2f0c){const _0x2ce06c=_0x5cf5ff;if(!currentTablesState||!currentTablesState[_0x451a60])return;const _0x147d68=_0x3c2f0c==='up'?_0x451a60-0x1:_0x451a60+0x1;if(_0x147d68<0x0||_0x147d68>=currentTablesState[_0x2ce06c(0x2ac)]){log(_0x2ce06c(0x260)+_0x451a60+_0x2ce06c(0x1e2),_0x2ce06c(0x2d9));return;}const _0x354400=currentTablesState[_0x451a60];currentTablesState[_0x451a60]=currentTablesState[_0x147d68],currentTablesState[_0x147d68]=_0x354400;const _0x5f174b=_0x2ce06c(0x2a2)+_0x354400[_0x2ce06c(0x22f)]+_0x2ce06c(0x25b);log(_0x5f174b,_0x2ce06c(0x2db));const _0x34e3ea=getContext();if(_0x34e3ea['chat']&&_0x34e3ea[_0x2ce06c(0x25d)]['length']>0x0){const _0x36fdfc=_0x34e3ea[_0x2ce06c(0x25d)][_0x34e3ea['chat'][_0x2ce06c(0x2ac)]-0x1];if(saveStateToMessage(currentTablesState,_0x36fdfc)){saveChat(),log(_0x2ce06c(0x2d6),_0x2ce06c(0x2db));return;}}log(_0x2ce06c(0x2bc),_0x2ce06c(0x1df)),saveChatDebounced();}export function updateTableRules(_0x24cdb2,_0x4ab488){const _0xb8d2e5=_0x5cf5ff;if(!currentTablesState||!currentTablesState[_0x24cdb2])return;const _0x19b3ca=currentTablesState[_0x24cdb2];_0x19b3ca[_0xb8d2e5(0x24d)]=_0x4ab488[_0xb8d2e5(0x24d)],_0x19b3ca[_0xb8d2e5(0x294)]=_0x4ab488['rule_add'],_0x19b3ca[_0xb8d2e5(0x1f3)]=_0x4ab488[_0xb8d2e5(0x1f3)],_0x19b3ca[_0xb8d2e5(0x255)]=_0x4ab488[_0xb8d2e5(0x255)],_0x19b3ca[_0xb8d2e5(0x2c8)]=_0x4ab488['charLimitRules'],_0x19b3ca[_0xb8d2e5(0x219)]=_0x4ab488[_0xb8d2e5(0x219)],delete _0x19b3ca[_0xb8d2e5(0x28b)];const _0x414c1b='表格\x20['+_0x19b3ca[_0xb8d2e5(0x22f)]+_0xb8d2e5(0x25e);log(_0x414c1b,_0xb8d2e5(0x230));const _0x56c8e=getContext();if(_0x56c8e[_0xb8d2e5(0x25d)]&&_0x56c8e[_0xb8d2e5(0x25d)][_0xb8d2e5(0x2ac)]>0x0){const _0x212d86=_0x56c8e[_0xb8d2e5(0x25d)][_0x56c8e['chat']['length']-0x1];if(saveStateToMessage(currentTablesState,_0x212d86)){saveChat();return;}}saveChatDebounced();}export function updateRow(_0x3381ae,_0x374e61,_0x37c172){const _0x4340a4=_0x5cf5ff;if(!currentTablesState||!currentTablesState[_0x3381ae]){log(_0x4340a4(0x21b)+_0x3381ae+_0x4340a4(0x29c),_0x4340a4(0x1df));return;}const _0x1e88f6=currentTablesState[_0x3381ae];if(_0x374e61>=_0x1e88f6[_0x4340a4(0x1f1)][_0x4340a4(0x2ac)]){log(_0x4340a4(0x206)+_0x374e61+'),已智能转换为在表格\x20['+_0x1e88f6[_0x4340a4(0x22f)]+_0x4340a4(0x284),'warn'),insertRow(_0x3381ae,_0x37c172);return;}const _0x327a7f=_0x1e88f6[_0x4340a4(0x1f1)][_0x374e61];for(const _0x1ebff4 in _0x37c172){const _0x4f0c9e=parseInt(_0x1ebff4,0xa);_0x4f0c9e<_0x327a7f[_0x4340a4(0x2ac)]&&(_0x327a7f[_0x4f0c9e]=_0x37c172[_0x4f0c9e],addHighlight(_0x3381ae,_0x374e61,_0x4f0c9e));}updatedTables[_0x4340a4(0x249)](_0x3381ae);const _0x54059f=_0x4340a4(0x27e)+_0x1e88f6[_0x4340a4(0x22f)]+_0x4340a4(0x1ff)+(_0x374e61+0x1)+_0x4340a4(0x214);log(_0x54059f,'info');const _0x15f758=getContext();if(_0x15f758[_0x4340a4(0x25d)]&&_0x15f758['chat']['length']>0x0){const _0x158f4e=_0x15f758[_0x4340a4(0x25d)][_0x15f758['chat'][_0x4340a4(0x2ac)]-0x1];if(saveStateToMessage(currentTablesState,_0x158f4e)){saveChat();return;}}saveChatDebounced();}export function clearAllTables(){const _0x29e187=_0x5cf5ff;if(!currentTablesState){log('无法清空:当前表格状态为空。',_0x29e187(0x1df));return;}currentTablesState['forEach']((_0x5bd7c7,_0x1ad3c8)=>{const _0x1738c2=_0x29e187;_0x5bd7c7[_0x1738c2(0x1f1)][_0x1738c2(0x2ac)]>0x0&&updatedTables[_0x1738c2(0x249)](_0x1ad3c8),_0x5bd7c7[_0x1738c2(0x1f1)]=[],_0x5bd7c7[_0x1738c2(0x226)]=[];}),log(_0x29e187(0x1da),_0x29e187(0x2d9));const _0x5b5a1a=getContext();if(_0x5b5a1a[_0x29e187(0x25d)]&&_0x5b5a1a[_0x29e187(0x25d)][_0x29e187(0x2ac)]>0x0){const _0x30c38c=_0x5b5a1a[_0x29e187(0x25d)][_0x5b5a1a[_0x29e187(0x25d)][_0x29e187(0x2ac)]-0x1];if(saveStateToMessage(currentTablesState,_0x30c38c)){saveChat(),log(_0x29e187(0x2b0),_0x29e187(0x2db)),toastr['success'](_0x29e187(0x26a),_0x29e187(0x26c));return;}}log(_0x29e187(0x1f5),_0x29e187(0x1df)),saveChatDebounced();}function checkTableRules(_0x531c5b){const _0x16f95c=_0x5cf5ff;let _0x6168b4=[];_0x531c5b[_0x16f95c(0x219)]&&_0x531c5b[_0x16f95c(0x219)]>0x0&&_0x531c5b['rows']['length']>_0x531c5b['rowLimitRule']&&_0x6168b4['push']('【当前('+_0x531c5b[_0x16f95c(0x22f)]+_0x16f95c(0x27b)+_0x531c5b[_0x16f95c(0x219)]+')行,请结合剧情缩减至('+_0x531c5b[_0x16f95c(0x219)]+_0x16f95c(0x2a4));const _0x2b029b=_0x531c5b[_0x16f95c(0x2c8)]||{};for(const _0x410d1c in _0x2b029b){const _0x2980db=parseInt(_0x410d1c,0xa),_0x957517=_0x2b029b[_0x2980db];if(_0x957517>0x0&&_0x2980db>=0x0&&_0x2980db<_0x531c5b[_0x16f95c(0x29f)][_0x16f95c(0x2ac)]){const _0x43c4a0=_0x531c5b[_0x16f95c(0x29f)][_0x2980db],_0x1466fc=[];_0x531c5b['rows'][_0x16f95c(0x1fe)]((_0x3d352d,_0x357fc5)=>{const _0x51d06f=_0x16f95c;if(_0x531c5b[_0x51d06f(0x226)]&&_0x531c5b['rowStatuses'][_0x357fc5]===_0x51d06f(0x20c))return;const _0x54e00a=_0x3d352d[_0x2980db]||'';_0x54e00a[_0x51d06f(0x2ac)]>_0x957517&&_0x1466fc[_0x51d06f(0x220)](_0x357fc5);});if(_0x1466fc[_0x16f95c(0x2ac)]>0x0){const _0x94c697=_0x1466fc[_0x16f95c(0x1e6)]('、');_0x6168b4[_0x16f95c(0x220)]('【当前('+_0x531c5b[_0x16f95c(0x22f)]+_0x16f95c(0x233)+_0x94c697+_0x16f95c(0x1f9)+_0x43c4a0+_0x16f95c(0x1e4)+_0x957517+')字限制,请进行缩减。】');}}}return _0x6168b4[_0x16f95c(0x1e6)]('\x0a');}export function convertTablesToCsvString(){const _0x343821=_0x5cf5ff;!currentTablesState&&loadTables();if(!currentTablesState)return'';let _0x993d17='';return currentTablesState[_0x343821(0x1fe)]((_0x439f41,_0x2d3dfe)=>{const _0x23413a=_0x343821;_0x993d17+=_0x23413a(0x2b2)+_0x2d3dfe+':'+_0x439f41[_0x23413a(0x22f)]+'\x0a',_0x993d17+=_0x23413a(0x2a1)+(_0x439f41[_0x23413a(0x24d)]||'无')+'\x0a';const _0x5b6851=_0x439f41[_0x23413a(0x22f)][_0x23413a(0x2bd)](/\s/g,'')+'内容';_0x993d17+='<'+_0x5b6851+'>\x0a';const _0x4202a3=_0x439f41[_0x23413a(0x29f)][_0x23413a(0x277)]((_0x413b38,_0x2d5295)=>_0x2d5295+':'+_0x413b38)[_0x23413a(0x1e6)](',');_0x993d17+=_0x23413a(0x272)+_0x4202a3+'\x0a';_0x439f41[_0x23413a(0x1f1)][_0x23413a(0x2ac)]===0x0||_0x439f41[_0x23413a(0x1f1)]['every']((_0x330072,_0x230b06)=>_0x439f41[_0x23413a(0x226)]&&_0x439f41[_0x23413a(0x226)][_0x230b06]===_0x23413a(0x20c))?_0x993d17+='(该表当前内容为空)\x0a':_0x439f41[_0x23413a(0x1f1)]['forEach']((_0x1a764e,_0x46527a)=>{const _0xe0ba17=_0x23413a;if(_0x439f41[_0xe0ba17(0x226)]&&_0x439f41[_0xe0ba17(0x226)][_0x46527a]===_0xe0ba17(0x20c))return;if(Array[_0xe0ba17(0x2d4)](_0x1a764e)){const _0x220f1a=_0x1a764e[_0xe0ba17(0x277)](_0x4f26c9=>{const _0x27a30d=_0xe0ba17;return _0x4f26c9===null||_0x4f26c9===undefined||_0x4f26c9===''?'未知':_0x4f26c9[_0x27a30d(0x298)]();})[_0xe0ba17(0x1e6)](',');_0x993d17+=_0x46527a+','+_0x220f1a+'\x0a';}});const _0x36ef0c=checkTableRules(_0x439f41);_0x36ef0c&&(_0x993d17+=_0x36ef0c+'\x0a'),_0x993d17+=''+_0x5b6851+'>\x0a',_0x993d17+='【增加】:\x20'+(_0x439f41[_0x23413a(0x294)]||'允许')+'\x0a',_0x993d17+=_0x23413a(0x22e)+(_0x439f41[_0x23413a(0x1f3)]||'允许')+'\x0a',_0x993d17+=_0x23413a(0x276)+(_0x439f41['rule_update']||'允许')+'\x0a',_0x2d3dfe{const _0x491a98=_0x154035;_0x358dd8+='\x0a<'+_0x3e21f5['name']+'>\x0a';const _0x3cef70='|\x20'+_0x3e21f5['headers'][_0x491a98(0x1e6)]('\x20|\x20')+'\x20|';_0x358dd8+=_0x3cef70+'\x0a';const _0x1d3a93='|'+_0x3e21f5[_0x491a98(0x29f)][_0x491a98(0x277)](()=>'---')[_0x491a98(0x1e6)]('|')+'|';_0x358dd8+=_0x1d3a93+'\x0a';const _0x422860=_0x3e21f5['rows']['filter']((_0x2f7eb5,_0x253c15)=>!_0x3e21f5[_0x491a98(0x226)]||_0x3e21f5[_0x491a98(0x226)][_0x253c15]!==_0x491a98(0x20c));_0x422860[_0x491a98(0x2ac)]>0x0?_0x422860['forEach'](_0x5a3af3=>{const _0x338b78=_0x491a98;if(Array[_0x338b78(0x2d4)](_0x5a3af3)){const _0xdfbcc2=_0x5a3af3[_0x338b78(0x277)](_0x18e7bd=>_0x18e7bd===null||_0x18e7bd===undefined||_0x18e7bd===''?'\x20':_0x18e7bd[_0x338b78(0x298)]()),_0x32e495='|\x20'+_0xdfbcc2[_0x338b78(0x1e6)]('\x20|\x20')+'\x20|';_0x358dd8+=_0x32e495+'\x0a';}}):_0x358dd8+=_0x491a98(0x282),_0x358dd8+=''+_0x3e21f5[_0x491a98(0x22f)]+'>\x0a';}),_0x358dd8[_0x154035(0x257)]();}loadTables();export function getBatchFillerRuleTemplate(){const _0x218b42=_0x5cf5ff;return extension_settings[extensionName]?.[_0x218b42(0x2dd)]??DEFAULT_AI_RULE_TEMPLATE;}export function saveBatchFillerRuleTemplate(_0xf75747){extension_settings[extensionName]['batch_filler_rule_template']=_0xf75747,saveSettingsDebounced();}export function getBatchFillerFlowTemplate(){const _0x1be54c=_0x5cf5ff;return extension_settings[extensionName]?.[_0x1be54c(0x24f)]??DEFAULT_AI_FLOW_TEMPLATE;}export function saveBatchFillerFlowTemplate(_0x510d77){const _0x3bfa83=_0x5cf5ff;extension_settings[extensionName][_0x3bfa83(0x24f)]=_0x510d77,saveSettingsDebounced();}export function getAiFlowTemplateForInjection(){const _0x49edc3=_0x5cf5ff;return extension_settings[extensionName]?.[_0x49edc3(0x265)]??DEFAULT_AI_FLOW_TEMPLATE;}export async function updateTableFromText(_0x50ca49){const _0x57320c=_0x5cf5ff;if(!_0x50ca49){log(_0x57320c(0x1ed),_0x57320c(0x2d9));return;}const _0x1790ea=_0x50ca49[_0x57320c(0x1f4)](/([\s\S]*?)<\/Amily2Edit>/);if(!_0x1790ea||!_0x1790ea[0x1]){log(_0x57320c(0x1e7),_0x57320c(0x2d9));return;}let _0x2ccf84=_0x1790ea[0x1][_0x57320c(0x2bd)](//g,'')[_0x57320c(0x257)]();if(!_0x2ccf84){log(_0x57320c(0x241),_0x57320c(0x230));return;}const _0xe68068=_0x2ccf84[_0x57320c(0x2c3)]('\x0a')[_0x57320c(0x2dc)](_0xe99f71=>_0xe99f71['trim']()!=='');log(_0x57320c(0x1ef)+_0xe68068[_0x57320c(0x2ac)]+_0x57320c(0x271),_0x57320c(0x230));const _0x29eaac={'insertRow':(_0x5411de,_0x2b8f1b)=>{const _0x1ec01c=_0x57320c;log(_0x1ec01c(0x23b)+_0x5411de+_0x1ec01c(0x26d)+JSON[_0x1ec01c(0x290)](_0x2b8f1b)+')',_0x1ec01c(0x230)),insertRow(_0x5411de,_0x2b8f1b);},'deleteRow':(_0xdcf451,_0x313e0a)=>{const _0x26435e=_0x57320c;log(_0x26435e(0x2e1)+_0xdcf451+_0x26435e(0x27a)+_0x313e0a+')',_0x26435e(0x230)),deleteRow(_0xdcf451,_0x313e0a);},'updateRow':(_0x1f1ab4,_0xf5032d,_0x23bf40)=>{const _0x1d9810=_0x57320c;log(_0x1d9810(0x2ba)+_0x1f1ab4+',\x20rowIndex='+_0xf5032d+',\x20data='+JSON[_0x1d9810(0x290)](_0x23bf40)+')',_0x1d9810(0x230)),updateRow(_0x1f1ab4,_0xf5032d,_0x23bf40);}};try{const _0xd97c67=Object[_0x57320c(0x291)](async function(){})[_0x57320c(0x21e)],_0xbbf377=new _0xd97c67(_0x57320c(0x207),'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20const\x20{\x20insertRow,\x20deleteRow,\x20updateRow\x20}\x20=\x20runner;\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+_0x2ccf84+_0x57320c(0x213));await _0xbbf377(_0x29eaac),log(_0x57320c(0x2a6),_0x57320c(0x2db)),toastr['success']('已根据AI的指示成功更新表格!','填表完成'),document[_0x57320c(0x244)](new CustomEvent('amily2-force-ui-reload'));}catch(_0xb0675d){log(_0x57320c(0x283)+_0xb0675d[_0x57320c(0x232)],_0x57320c(0x1df)),toastr[_0x57320c(0x1df)](_0x57320c(0x2c5)+_0xb0675d[_0x57320c(0x232)],_0x57320c(0x26e));}}export function saveAiTemplate(_0x1e8526){extension_settings[extensionName]['amily2_ai_template']=_0x1e8526,saveSettingsDebounced();}export function getAiTemplate(){return getAiFlowTemplateForInjection();}function exportPresetBase(_0x5e1829=![]){const _0x590252=_0x5cf5ff;if(!currentTablesState){log(_0x590252(0x2b4),'error'),toastr[_0x590252(0x1df)](_0x590252(0x2a5));return;}let _0x963da7,_0x2948f7,_0x217d44;_0x5e1829?(_0x963da7=JSON['parse'](JSON[_0x590252(0x290)](currentTablesState)),_0x2948f7=_0x590252(0x27c),_0x217d44=_0x590252(0x254)):(_0x963da7=currentTablesState[_0x590252(0x277)](_0x5eb455=>({'name':_0x5eb455['name'],'headers':_0x5eb455[_0x590252(0x29f)],'columnWidths':_0x5eb455[_0x590252(0x287)]||[],'note':_0x5eb455['note'],'rule_add':_0x5eb455[_0x590252(0x294)],'rule_delete':_0x5eb455[_0x590252(0x1f3)],'rule_update':_0x5eb455[_0x590252(0x255)],'charLimitRules':_0x5eb455['charLimitRules']||{},'rowLimitRule':_0x5eb455[_0x590252(0x219)]||0x0,'rows':[],'rowStatuses':[]})),_0x2948f7=_0x590252(0x28c),_0x217d44=_0x590252(0x23c));const _0x3ac02a={'version':_0x590252(0x21a),'batchFillerRuleTemplate':getBatchFillerRuleTemplate(),'batchFillerFlowTemplate':getBatchFillerFlowTemplate(),'tables':_0x963da7},_0x351af9=new Blob([JSON[_0x590252(0x290)](_0x3ac02a,null,0x2)],{'type':_0x590252(0x215)}),_0x334f8a=URL[_0x590252(0x225)](_0x351af9),_0x5965a0=document['createElement']('a');_0x5965a0[_0x590252(0x273)]=_0x334f8a,_0x5965a0[_0x590252(0x1e9)]=_0x590252(0x248)+_0x217d44+'-'+new Date()[_0x590252(0x208)]()[_0x590252(0x22a)](0x0,0xa)+_0x590252(0x1ec),document[_0x590252(0x2b5)][_0x590252(0x237)](_0x5965a0),_0x5965a0['click'](),document[_0x590252(0x2b5)][_0x590252(0x285)](_0x5965a0),URL[_0x590252(0x22d)](_0x334f8a),log('【'+_0x217d44+'】已成功导出。',_0x590252(0x2db)),toastr['success']('【'+_0x217d44+_0x590252(0x228),_0x590252(0x267));}export function exportPreset(){exportPresetBase(![]);}export function exportPresetFull(){exportPresetBase(!![]);}export function importPreset(_0x2f47f4){const _0x491693=_0x5cf5ff,_0x38e956=document[_0x491693(0x245)](_0x491693(0x1f6));_0x38e956[_0x491693(0x25f)]=_0x491693(0x2bf),_0x38e956['accept']=_0x491693(0x1ec),_0x38e956[_0x491693(0x212)]=_0x3193fd=>{const _0x1cee3b=_0x491693,_0x394510=_0x3193fd[_0x1cee3b(0x2a7)]['files'][0x0];if(!_0x394510)return;const _0x429a3d=new FileReader();_0x429a3d[_0x1cee3b(0x2be)]=_0x496a98=>{const _0x4de077=_0x1cee3b;try{const _0x5e1293=JSON[_0x4de077(0x2df)](_0x496a98[_0x4de077(0x2a7)][_0x4de077(0x234)]);if(!_0x5e1293[_0x4de077(0x2cc)]||!Array[_0x4de077(0x2d4)](_0x5e1293['tables']))throw new Error(_0x4de077(0x263));const _0x298f41=window[_0x4de077(0x222)]('【警告】\x0a\x0a导入操作将完全覆盖您当前的AI指令模板和所有表格(包括结构和内容)。\x0a\x0a此操作不可逆,是否确定要继续?');if(!_0x298f41){log('用户取消了导入操作。',_0x4de077(0x230)),toastr[_0x4de077(0x230)](_0x4de077(0x296));return;}if(_0x5e1293[_0x4de077(0x2cc)]==='Amily2-Table-Preset-v3.0-separated_templates')saveBatchFillerRuleTemplate(_0x5e1293[_0x4de077(0x29e)]||''),saveBatchFillerFlowTemplate(_0x5e1293[_0x4de077(0x2cb)]||''),saveAiTemplate(_0x5e1293[_0x4de077(0x239)]||'');else{if(_0x5e1293['aiRuleTemplate']!==undefined&&_0x5e1293[_0x4de077(0x2c2)]!==undefined)saveBatchFillerRuleTemplate(_0x5e1293['aiRuleTemplate']||''),saveBatchFillerFlowTemplate(_0x5e1293[_0x4de077(0x2c2)]||''),saveAiTemplate(_0x5e1293[_0x4de077(0x2c2)]||'');else _0x5e1293[_0x4de077(0x252)]?(saveBatchFillerRuleTemplate(''),saveBatchFillerFlowTemplate(_0x5e1293[_0x4de077(0x252)]||''),saveAiTemplate(_0x5e1293[_0x4de077(0x252)]||'')):log('导入的预设中缺少指令模板字段,模板将不会被更新。',_0x4de077(0x2d9));}const _0x4f4f06=_0x5e1293[_0x4de077(0x1f8)];_0x4f4f06[_0x4de077(0x1fe)](_0x1dadc8=>{const _0x465821=_0x4de077;if(_0x1dadc8[_0x465821(0x22f)]===undefined||_0x1dadc8[_0x465821(0x29f)]===undefined||_0x1dadc8[_0x465821(0x1f1)]===undefined)throw new Error(_0x465821(0x201)+JSON[_0x465821(0x290)](_0x1dadc8));if(_0x1dadc8['note']===undefined)_0x1dadc8[_0x465821(0x24d)]='无';if(_0x1dadc8[_0x465821(0x294)]===undefined)_0x1dadc8[_0x465821(0x294)]='允许';if(_0x1dadc8[_0x465821(0x1f3)]===undefined)_0x1dadc8['rule_delete']='允许';if(_0x1dadc8[_0x465821(0x255)]===undefined)_0x1dadc8[_0x465821(0x255)]='允许';if(_0x1dadc8[_0x465821(0x28b)]&&!_0x1dadc8[_0x465821(0x2c8)])_0x1dadc8[_0x465821(0x2c8)]={},_0x1dadc8['charLimitRule'][_0x465821(0x29b)]!==-0x1&&_0x1dadc8[_0x465821(0x28b)][_0x465821(0x209)]>0x0&&(_0x1dadc8['charLimitRules'][_0x1dadc8['charLimitRule'][_0x465821(0x29b)]]=_0x1dadc8['charLimitRule'][_0x465821(0x209)]);else _0x1dadc8['charLimitRules']===undefined&&(_0x1dadc8[_0x465821(0x2c8)]={});delete _0x1dadc8['charLimitRule'],!_0x1dadc8[_0x465821(0x226)]&&(_0x1dadc8['rowStatuses']=Array(_0x1dadc8[_0x465821(0x1f1)][_0x465821(0x2ac)])[_0x465821(0x2d8)]('normal')),_0x1dadc8[_0x465821(0x219)]===undefined&&(_0x1dadc8[_0x465821(0x219)]=0x0),_0x1dadc8[_0x465821(0x287)]===undefined&&(_0x1dadc8[_0x465821(0x287)]=[]);}),setMemoryState(_0x4f4f06);const _0x3e173e=getContext();if(_0x3e173e[_0x4de077(0x25d)]&&_0x3e173e[_0x4de077(0x25d)][_0x4de077(0x2ac)]>0x0){const _0x2f6919=_0x3e173e[_0x4de077(0x25d)][_0x3e173e[_0x4de077(0x25d)][_0x4de077(0x2ac)]-0x1];saveStateToMessage(getMemoryState(),_0x2f6919)&&(saveChat(),log(_0x4de077(0x1f0),'success'));}else saveChatDebounced();log(_0x4de077(0x24c),_0x4de077(0x2db)),toastr[_0x4de077(0x2db)]('预设已成功导入!',_0x4de077(0x280)),typeof _0x2f47f4===_0x4de077(0x2aa)&&_0x2f47f4();}catch(_0x59cca0){log('导入预设失败:\x20'+_0x59cca0['message'],_0x4de077(0x1df)),toastr[_0x4de077(0x1df)](_0x4de077(0x20d)+_0x59cca0[_0x4de077(0x232)],'错误');}},_0x429a3d[_0x1cee3b(0x236)](_0x394510);},_0x38e956['click']();}function _0x8bba(_0x526c0b,_0x50cdd5){const _0x2ce62b=_0x2ce6();return _0x8bba=function(_0x8bbac3,_0x4d35ba){_0x8bbac3=_0x8bbac3-0x1da;let _0x1360e0=_0x2ce62b[_0x8bbac3];return _0x1360e0;},_0x8bba(_0x526c0b,_0x50cdd5);}export async function rollbackState(){const _0x5496c2=_0x5cf5ff,_0xdae7dd=getContext();if(!_0xdae7dd||!_0xdae7dd[_0x5496c2(0x25d)]||_0xdae7dd[_0x5496c2(0x25d)][_0x5496c2(0x2ac)]<0x2)return log(_0x5496c2(0x292),_0x5496c2(0x2d9)),toastr['warning'](_0x5496c2(0x256)),![];const _0x4946de=_0xdae7dd[_0x5496c2(0x25d)],_0x14c70b=_0x4946de['length']-0x1,_0x1e1fd2=_0x4946de[_0x14c70b];log(_0x5496c2(0x24b)+(_0x14c70b-0x1)+_0x5496c2(0x295),_0x5496c2(0x230));const _0x169bee=loadTables(_0x14c70b);if(!_0x169bee)return log('未能在上一楼找到可用的表格状态,无法回退。',_0x5496c2(0x1df)),toastr[_0x5496c2(0x1df)](_0x5496c2(0x2ad)),![];setMemoryState(_0x169bee);if(saveStateToMessage(_0x169bee,_0x1e1fd2))await saveChat(),log(_0x5496c2(0x2b3),'success');else return log(_0x5496c2(0x1ee),_0x5496c2(0x1df)),toastr[_0x5496c2(0x1df)](_0x5496c2(0x242)),![];return renderTables(),updateOrInsertTableInChat(),log(_0x5496c2(0x2bb),_0x5496c2(0x230)),!![];}export async function rollbackAndRefill(){const _0x156e4c=_0x5cf5ff;toastr[_0x156e4c(0x230)]('正在执行回退并重新填表...');const _0x2ad974=await rollbackState();if(!_0x2ad974){toastr[_0x156e4c(0x1df)]('状态回退失败,已中止操作。');return;}toastr[_0x156e4c(0x2db)](_0x156e4c(0x1dd));const _0x40d147=getContext(),_0x54be8e=_0x40d147['chat'][_0x40d147[_0x156e4c(0x25d)][_0x156e4c(0x2ac)]-0x1];try{await fillWithSecondaryApi(_0x54be8e,!![]),log('回退并重新填表操作完成。',_0x156e4c(0x2db));}catch(_0x4855e4){log(_0x156e4c(0x229)+_0x4855e4['message'],_0x156e4c(0x1df)),toastr[_0x156e4c(0x1df)](_0x156e4c(0x2ce)+_0x4855e4['message']);}}export function updateColumnWidth(_0x5e363a,_0x3a8588,_0x9ddf4e){const _0x3b0670=_0x5cf5ff;if(!currentTablesState||!currentTablesState[_0x5e363a])return;const _0x4038ee=currentTablesState[_0x5e363a];!_0x4038ee[_0x3b0670(0x287)]&&(_0x4038ee['columnWidths']=[]);while(_0x4038ee[_0x3b0670(0x287)]['length']<_0x4038ee['headers'][_0x3b0670(0x2ac)]){_0x4038ee[_0x3b0670(0x287)][_0x3b0670(0x220)](null);}_0x4038ee['columnWidths'][_0x3a8588]=_0x9ddf4e;const _0x2c3de6=getContext();if(_0x2c3de6[_0x3b0670(0x25d)]&&_0x2c3de6[_0x3b0670(0x25d)][_0x3b0670(0x2ac)]>0x0){const _0x2c2dab=_0x2c3de6['chat'][_0x2c3de6['chat']['length']-0x1];if(saveStateToMessage(currentTablesState,_0x2c2dab)){saveChat();return;}}saveChatDebounced();}export function isCurrentTablesEmpty(){const _0x3d48ee=_0x5cf5ff,_0x3b5374=getMemoryState();if(!_0x3b5374||_0x3b5374[_0x3d48ee(0x2ac)]===0x0)return!![];return _0x3b5374[_0x3d48ee(0x1ea)](_0x5494d7=>!_0x5494d7[_0x3d48ee(0x1f1)]||_0x5494d7[_0x3d48ee(0x1f1)][_0x3d48ee(0x2ac)]===0x0);}export function clearGlobalPreset(){const _0x30cd67=_0x5cf5ff;if(extension_settings[extensionName]&&extension_settings[extensionName]['global_table_preset']){const _0x546e77=window[_0x30cd67(0x222)](_0x30cd67(0x264));_0x546e77?(delete extension_settings[extensionName][_0x30cd67(0x27f)],saveSettingsDebounced(),log(_0x30cd67(0x20e),'success'),toastr['success'](_0x30cd67(0x262),_0x30cd67(0x28a))):(log(_0x30cd67(0x202),'info'),toastr[_0x30cd67(0x230)](_0x30cd67(0x21d)));}else log(_0x30cd67(0x20f),_0x30cd67(0x230)),toastr[_0x30cd67(0x230)](_0x30cd67(0x268),'提示');}export function importGlobalPreset(_0x24274c){const _0x3ea7b3=_0x5cf5ff,_0x5c73bb=document['createElement']('input');_0x5c73bb[_0x3ea7b3(0x25f)]='file',_0x5c73bb['accept']=_0x3ea7b3(0x1ec),_0x5c73bb['onchange']=_0x494cea=>{const _0x313fc1=_0x3ea7b3,_0x50f239=_0x494cea[_0x313fc1(0x2a7)][_0x313fc1(0x2b1)][0x0];if(!_0x50f239)return;const _0x4d1998=new FileReader();_0x4d1998[_0x313fc1(0x2be)]=_0x1fcffe=>{const _0x3cb5d3=_0x313fc1;try{const _0x157a3d=JSON[_0x3cb5d3(0x2df)](_0x1fcffe['target']['result']);if(!_0x157a3d['version']||!Array[_0x3cb5d3(0x2d4)](_0x157a3d[_0x3cb5d3(0x1f8)]))throw new Error(_0x3cb5d3(0x263));const _0x4cf22a=window[_0x3cb5d3(0x222)]('【全局预设导入】\x0a\x0a这将把选定的预设设置为所有新聊天的默认表格。\x0a\x0a此操作将覆盖任何已存在的全局预设,是否确定?');if(!_0x4cf22a){log(_0x3cb5d3(0x22b),_0x3cb5d3(0x230)),toastr[_0x3cb5d3(0x230)](_0x3cb5d3(0x21d));return;}const _0x62444f=_0x157a3d[_0x3cb5d3(0x1f8)][_0x3cb5d3(0x277)](_0x54581d=>({'name':_0x54581d[_0x3cb5d3(0x22f)],'headers':_0x54581d[_0x3cb5d3(0x29f)],'note':_0x54581d['note'],'rule_add':_0x54581d[_0x3cb5d3(0x294)],'rule_delete':_0x54581d[_0x3cb5d3(0x1f3)],'rule_update':_0x54581d[_0x3cb5d3(0x255)],'rows':[]}));!extension_settings[extensionName]&&(extension_settings[extensionName]={});extension_settings[extensionName]['global_table_preset']={'version':_0x157a3d[_0x3cb5d3(0x2cc)],'tables':_0x62444f,'batchFillerRuleTemplate':_0x157a3d[_0x3cb5d3(0x29e)],'batchFillerFlowTemplate':_0x157a3d[_0x3cb5d3(0x2cb)]},saveSettingsDebounced();if(_0x157a3d[_0x3cb5d3(0x2cc)]===_0x3cb5d3(0x21a))saveBatchFillerRuleTemplate(_0x157a3d[_0x3cb5d3(0x29e)]||''),saveBatchFillerFlowTemplate(_0x157a3d[_0x3cb5d3(0x2cb)]||''),saveAiTemplate(_0x157a3d['injectionFlowTemplate']||'');else{if(_0x157a3d[_0x3cb5d3(0x1f2)]!==undefined&&_0x157a3d['aiFlowTemplate']!==undefined)saveBatchFillerRuleTemplate(_0x157a3d[_0x3cb5d3(0x1f2)]||''),saveBatchFillerFlowTemplate(_0x157a3d[_0x3cb5d3(0x2c2)]||''),saveAiTemplate(_0x157a3d['aiFlowTemplate']||'');else _0x157a3d[_0x3cb5d3(0x252)]&&(saveBatchFillerRuleTemplate(''),saveBatchFillerFlowTemplate(_0x157a3d['aiTemplate']||''),saveAiTemplate(_0x157a3d['aiTemplate']||''));}log(_0x3cb5d3(0x23e),'success'),toastr[_0x3cb5d3(0x2db)]('全局预设已设置!新聊天将默认使用此预设。','设置成功'),typeof _0x24274c===_0x3cb5d3(0x2aa)&&_0x24274c();}catch(_0x65996a){log('导入全局预设失败:\x20'+_0x65996a[_0x3cb5d3(0x232)],_0x3cb5d3(0x1df)),toastr[_0x3cb5d3(0x1df)]('导入失败:'+_0x65996a[_0x3cb5d3(0x232)],'错误');}},_0x4d1998[_0x313fc1(0x236)](_0x50f239);},_0x5c73bb[_0x3ea7b3(0x258)]();}
diff --git a/core/table-system/secondary-filler.js b/core/table-system/secondary-filler.js
index 87feb2a..16fba86 100644
--- a/core/table-system/secondary-filler.js
+++ b/core/table-system/secondary-filler.js
@@ -234,13 +234,11 @@ export async function fillWithSecondaryApi(latestMessage, forceRun = false) {
if (currentContext.chat && currentContext.chat.length > 0) {
const lastMessage = currentContext.chat[currentContext.chat.length - 1];
if (saveStateToMessage(getMemoryState(), lastMessage)) {
- saveChat();
renderTables();
updateOrInsertTableInChat();
- return;
}
}
- saveChatDebounced();
+ saveChat();
} catch (error) {
console.error(`[Amily2-副API] 发生严重错误:`, error);
diff --git a/core/tavern-helper/Wrapperiframe.js b/core/tavern-helper/Wrapperiframe.js
new file mode 100644
index 0000000..bffad56
--- /dev/null
+++ b/core/tavern-helper/Wrapperiframe.js
@@ -0,0 +1,36 @@
+(function(){
+ if (window.frameElement) {
+ window.frameElement.style.height = 'auto';
+ }
+ function getGlobal() {
+ if (typeof self !== 'undefined') { return self; }
+ if (typeof window !== 'undefined') { return window; }
+ if (typeof global !== 'undefined') { return global; }
+ throw new Error('unable to locate global object');
+ }
+ const globalScope = getGlobal();
+ if (globalScope.generate_send_button_onclick) {
+ globalScope.generate_send_button_onclick_old = globalScope.generate_send_button_onclick;
+ globalScope.generate_send_button_onclick = function(event) {
+ try {
+ const textarea = document.getElementById('send_textarea');
+ if (textarea && textarea.value) {
+ const customEvent = new CustomEvent('xb-send-message', {
+ detail: {
+ message: textarea.value,
+ event: event
+ },
+ bubbles: true,
+ cancelable: true
+ });
+ if (!window.dispatchEvent(customEvent)) {
+ return;
+ }
+ }
+ } catch (e) {
+ console.error('Error in xb-send-message event dispatch:', e);
+ }
+ globalScope.generate_send_button_onclick_old(event);
+ };
+ }
+})();
diff --git a/core/tavern-helper/iframe_client.js b/core/tavern-helper/iframe_client.js
new file mode 100644
index 0000000..0fbca7d
--- /dev/null
+++ b/core/tavern-helper/iframe_client.js
@@ -0,0 +1,31 @@
+
+function initializeAmilyClient() {
+ console.log('[Amily2-IframeClient] 正在初始化...');
+
+ document.body.addEventListener('click', function(event) {
+ const target = event.target.closest('[data-amily-action]');
+
+ if (target) {
+ const action = target.dataset.amilyAction;
+ const detail = { ...target.dataset };
+
+ delete detail.amilyAction;
+
+ console.log(`[Amily2-IframeClient] 触发动作: ${action}`, detail);
+
+ if (window.AmilySimpleAPI && typeof window.AmilySimpleAPI.post === 'function') {
+ window.AmilySimpleAPI.post(action, detail);
+ } else {
+ console.error('[Amily2-IframeClient] AmilySimpleAPI 不可用。');
+ }
+ }
+ });
+
+ console.log('[Amily2-IframeClient] 客户端脚本已加载并就绪。');
+}
+
+if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', initializeAmilyClient);
+} else {
+ initializeAmilyClient();
+}
diff --git a/core/tavern-helper/main.js b/core/tavern-helper/main.js
index 432d6b8..a342b26 100644
--- a/core/tavern-helper/main.js
+++ b/core/tavern-helper/main.js
@@ -1,149 +1,619 @@
-import {
- world_names,
- loadWorldInfo,
- saveWorldInfo,
- createNewWorldInfo,
- createWorldInfoEntry
-} from "/scripts/world-info.js";
-import { characters } from "/script.js";
-import { getContext } from "/scripts/extensions.js";
-import { executeSlashCommandsWithOptions } from '/scripts/slash-commands.js';
-
-
-class AmilyHelper {
-
- async getLorebooks() {
- return [...world_names];
- }
-
- async getCharLorebooks(options = { type: 'all' }) {
- try {
- const context = getContext();
- if (!context || !context.characterId) {
- console.warn('[Amily助手] 无法获取当前角色上下文。');
- return { primary: null, additional: [] };
- }
- const character = characters[context.characterId];
- const primary = character?.data?.extensions?.world;
- return { primary: primary || null, additional: [] };
- } catch (error) {
- console.error('[Amily助手] 获取角色世界书时出错:', error);
- return { primary: null, additional: [] };
- }
- }
-
- async getLorebookEntries(bookName) {
- try {
- const bookData = await loadWorldInfo(bookName);
- if (!bookData || !bookData.entries) {
- return [];
- }
- return Object.entries(bookData.entries).map(([uid, entry]) => ({
- uid: parseInt(uid),
- comment: entry.comment || '无标题条目',
- content: entry.content || '',
- key: entry.key || [],
- enabled: !entry.disable,
- constant: entry.constant || false,
- position: entry.position || 4,
- depth: entry.depth || 998,
- }));
- } catch (error) {
- console.error(`[Amily助手] 获取世界书《${bookName}》条目时出错:`, error);
- return [];
- }
- }
-
- async setLorebookEntries(bookName, entries) {
- try {
- const bookData = await loadWorldInfo(bookName);
- if (!bookData) {
- console.error(`[Amily助手] 更新失败:找不到世界书《${bookName}》。`);
- return false;
- }
- for (const entryUpdate of entries) {
- const existingEntry = bookData.entries[entryUpdate.uid];
- if (existingEntry) {
- if (entryUpdate.content !== undefined) existingEntry.content = entryUpdate.content;
- if (entryUpdate.enabled !== undefined) existingEntry.disable = !entryUpdate.enabled;
- if (entryUpdate.comment !== undefined) existingEntry.comment = entryUpdate.comment;
- if (entryUpdate.key !== undefined) existingEntry.key = entryUpdate.key;
- if (entryUpdate.constant !== undefined) existingEntry.constant = entryUpdate.constant;
- if (entryUpdate.position !== undefined) existingEntry.position = entryUpdate.position;
- if (entryUpdate.depth !== undefined) existingEntry.depth = entryUpdate.depth;
- }
- }
- await saveWorldInfo(bookName, bookData, true);
- return true;
- } catch (error) {
- console.error(`[Amily助手] 更新世界书《${bookName}》条目时出错:`, error);
- return false;
- }
- }
-
- async createLorebookEntries(bookName, entries) {
- try {
- let bookData = await loadWorldInfo(bookName);
- if (!bookData) {
- console.warn(`[Amily助手] 世界书《${bookName}》不存在,将自动创建。`);
- await this.createLorebook(bookName);
- bookData = await loadWorldInfo(bookName);
- if (!bookData) {
- throw new Error(`创建并加载世界书《${bookName}》失败。`);
- }
- }
-
- for (const newEntryData of entries) {
- const newEntry = createWorldInfoEntry(bookName, bookData);
- Object.assign(newEntry, {
- comment: newEntryData.comment || '新条目',
- content: newEntryData.content || '',
- key: newEntryData.key || [],
- constant: newEntryData.constant || false,
- position: newEntryData.position ?? 4,
- depth: newEntryData.depth ?? 998,
- disable: !(newEntryData.enabled ?? true),
- });
- }
- await saveWorldInfo(bookName, bookData, true);
- return true;
- } catch (error) {
- console.error(`[Amily助手] 在世界书《${bookName}》中创建新条目时出错:`, error);
- return false;
- }
- }
-
- async createLorebook(bookName) {
- try {
- if (world_names.includes(bookName)) {
- console.warn(`[Amily助手] 创建失败:世界书《${bookName}》已存在。`);
- return false;
- }
- await createNewWorldInfo(bookName);
- if (!world_names.includes(bookName)) {
- world_names.push(bookName);
- world_names.sort();
- }
- return true;
- } catch (error) {
- console.error(`[Amily助手] 创建世界书《${bookName}》时出错:`, error);
- return false;
- }
- }
-
- async triggerSlash(command) {
- try {
- console.log(`[Amily助手] 正在执行斜杠命令: ${command}`);
- const result = await executeSlashCommandsWithOptions(command);
- if (result.isError) {
- throw new Error(result.errorMessage);
- }
- return result.pipe;
- } catch (error) {
- console.error(`[Amily助手] 执行斜杠命令 '${command}' 时出错:`, error);
- throw error;
- }
- }
-}
-
-export const amilyHelper = new AmilyHelper();
+import {
+ world_names,
+ loadWorldInfo,
+ saveWorldInfo,
+ createNewWorldInfo,
+ createWorldInfoEntry,
+ reloadEditor
+} from "/scripts/world-info.js";
+import {
+ characters,
+ eventSource,
+ event_types,
+ chat,
+ reloadCurrentChat,
+ saveChatConditional,
+ name1,
+ name2,
+ addOneMessage,
+ messageFormatting,
+ substituteParamsExtended
+} from "/script.js";
+import { getContext } from "/scripts/extensions.js";
+import { executeSlashCommandsWithOptions } from '/scripts/slash-commands.js';
+
+
+class AmilyHelper {
+
+ // ==================== Chat Message 相关方法 ====================
+
+ getChatMessages(range, options = {}) {
+ const { role = 'all', hide_state = 'all', include_swipes = false, include_swipe = false } = options;
+ const includeSwipes = include_swipes || include_swipe;
+
+ if (!chat || !Array.isArray(chat)) {
+ throw new Error('聊天数组不可用');
+ }
+
+ let start, end;
+ const rangeStr = String(range);
+
+ if (rangeStr.match(/^(-?\d+)$/)) {
+ const value = Number(rangeStr);
+ start = end = value < 0 ? chat.length + value : value;
+ } else {
+ const match = rangeStr.match(/^(-?\d+)-(-?\d+)$/);
+ if (!match) {
+ throw new Error(`无效的消息范围: ${range}`);
+ }
+ const [, s, e] = match;
+ const startVal = Number(s) < 0 ? chat.length + Number(s) : Number(s);
+ const endVal = Number(e) < 0 ? chat.length + Number(e) : Number(e);
+ start = Math.min(startVal, endVal);
+ end = Math.max(startVal, endVal);
+ }
+
+ if (start < 0 || end >= chat.length || start > end) {
+ throw new Error(`消息范围超出界限: ${range}`);
+ }
+
+ const getRole = (msg) => {
+ if (msg.is_system) return 'system';
+ return msg.is_user ? 'user' : 'assistant';
+ };
+
+ const messages = [];
+ for (let i = start; i <= end; i++) {
+ const msg = chat[i];
+ if (!msg) continue;
+
+ const msgRole = getRole(msg);
+
+ if (role !== 'all' && msgRole !== role) continue;
+
+ if (hide_state !== 'all') {
+ if ((hide_state === 'hidden') !== msg.is_system) continue;
+ }
+
+ const swipe_id = msg.swipe_id ?? 0;
+ const swipes = msg.swipes ?? [msg.mes];
+ const swipes_data = msg.variables ?? [{}];
+ const swipes_info = msg.swipes_info ?? [msg.extra ?? {}];
+
+ if (includeSwipes) {
+ messages.push({
+ message_id: i,
+ name: msg.name,
+ role: msgRole,
+ is_hidden: msg.is_system,
+ swipe_id: swipe_id,
+ swipes: swipes,
+ swipes_data: swipes_data,
+ swipes_info: swipes_info
+ });
+ } else {
+ messages.push({
+ message_id: i,
+ name: msg.name,
+ role: msgRole,
+ is_hidden: msg.is_system,
+ message: msg.mes,
+ data: swipes_data[swipe_id],
+ extra: swipes_info[swipe_id]
+ });
+ }
+ }
+
+ return messages;
+ }
+
+ async setChatMessages(chat_messages, options = {}) {
+ const { refresh = 'affected' } = options;
+
+ if (!Array.isArray(chat_messages)) {
+ throw new Error('chat_messages 必须是数组');
+ }
+
+ for (const chatMsg of chat_messages) {
+ const msg = chat[chatMsg.message_id];
+ if (!msg) continue;
+
+ if (chatMsg.name !== undefined) msg.name = chatMsg.name;
+ if (chatMsg.role !== undefined) msg.is_user = chatMsg.role === 'user';
+ if (chatMsg.is_hidden !== undefined) msg.is_system = chatMsg.is_hidden;
+
+ if (chatMsg.message !== undefined) {
+ msg.mes = chatMsg.message;
+ if (msg.swipes) {
+ msg.swipes[msg.swipe_id ?? 0] = chatMsg.message;
+ }
+ }
+
+ if (chatMsg.data !== undefined) {
+ if (!msg.variables) {
+ msg.variables = Array(msg.swipes?.length ?? 1).fill({});
+ }
+ msg.variables[msg.swipe_id ?? 0] = chatMsg.data;
+ }
+
+ if (chatMsg.extra !== undefined) {
+ if (!msg.swipes_info) {
+ msg.swipes_info = Array(msg.swipes?.length ?? 1).fill({});
+ }
+ msg.extra = chatMsg.extra;
+ msg.swipes_info[msg.swipe_id ?? 0] = chatMsg.extra;
+ }
+ }
+
+ await saveChatConditional();
+
+ if (refresh === 'all') {
+ await reloadCurrentChat();
+ } else if (refresh === 'affected') {
+ for (const chatMsg of chat_messages) {
+ const $mes = $(`div.mes[mesid="${chatMsg.message_id}"]`);
+ if ($mes.length) {
+ const msg = chat[chatMsg.message_id];
+ $mes.find('.mes_text').empty().append(
+ messageFormatting(msg.mes, msg.name, msg.is_system, msg.is_user, chatMsg.message_id)
+ );
+ }
+ }
+ }
+
+ console.log(`[Amily助手] 已修改消息: ${chat_messages.map(m => m.message_id).join(', ')}`);
+ }
+
+
+ async setChatMessage(field_values, message_id, {
+ swipe_id = 'current',
+ refresh = 'display_and_render_current'
+ } = {}) {
+ field_values = typeof field_values === 'string' ? { message: field_values } : field_values;
+
+ if (typeof swipe_id !== 'number' && swipe_id !== 'current') {
+ throw new Error(`提供的 swipe_id 无效, 请提供 'current' 或序号, 你提供的是: ${swipe_id}`);
+ }
+ if (!['none', 'display_current', 'display_and_render_current', 'all'].includes(refresh)) {
+ throw new Error(
+ `提供的 refresh 无效, 请提供 'none', 'display_current', 'display_and_render_current' 或 'all', 你提供的是: ${refresh}`
+ );
+ }
+
+ const chat_message = chat[message_id];
+ if (!chat_message) {
+ console.warn(`[Amily助手] 未找到第 ${message_id} 楼的消息`);
+ return;
+ }
+
+ const add_swipes_if_required = () => {
+ if (swipe_id === 'current') {
+ return false;
+ }
+
+ if (swipe_id == 0 || (chat_message.swipes && swipe_id < chat_message.swipes.length)) {
+ return true;
+ }
+
+ if (!chat_message.swipes) {
+ chat_message.swipe_id = 0;
+ chat_message.swipes = [chat_message.mes];
+ chat_message.variables = [{}];
+ }
+ for (let i = chat_message.swipes.length; i <= swipe_id; ++i) {
+ chat_message.swipes.push('');
+ chat_message.variables.push({});
+ }
+ return true;
+ };
+
+ const swipe_id_previous_index = chat_message.swipe_id ?? 0;
+ const swipe_id_to_set_index = swipe_id == 'current' ? swipe_id_previous_index : swipe_id;
+ const swipe_id_to_use_index = refresh != 'none' ? swipe_id_to_set_index : swipe_id_previous_index;
+ const message = field_values.message ??
+ (chat_message.swipes ? chat_message.swipes[swipe_id_to_set_index] : undefined) ??
+ chat_message.mes;
+
+ const update_chat_message = () => {
+ const message_demacroed = substituteParamsExtended(message);
+
+ if (field_values.data) {
+ if (!chat_message.variables) {
+ chat_message.variables = [];
+ }
+ chat_message.variables[swipe_id_to_set_index] = field_values.data;
+ }
+
+ if (chat_message.swipes) {
+ chat_message.swipes[swipe_id_to_set_index] = message_demacroed;
+ chat_message.swipe_id = swipe_id_to_use_index;
+ }
+
+ if (swipe_id_to_use_index === swipe_id_to_set_index) {
+ chat_message.mes = message_demacroed;
+ }
+ };
+
+ const update_partial_html = async (should_update_swipe) => {
+ const mes_html = $(`div.mes[mesid="${message_id}"]`);
+ if (!mes_html.length) {
+ return;
+ }
+
+ if (should_update_swipe) {
+ mes_html.find('.swipes-counter').text(`${swipe_id_to_use_index + 1}\u200b/\u200b${chat_message.swipes.length}`);
+ }
+
+ if (refresh != 'none') {
+ mes_html
+ .find('.mes_text')
+ .empty()
+ .append(
+ messageFormatting(message, chat_message.name, chat_message.is_system, chat_message.is_user, message_id)
+ );
+ if (refresh === 'display_and_render_current') {
+ await eventSource.emit(
+ chat_message.is_user ? event_types.USER_MESSAGE_RENDERED : event_types.CHARACTER_MESSAGE_RENDERED,
+ message_id
+ );
+ }
+ }
+ };
+
+ const should_update_swipe = add_swipes_if_required();
+ update_chat_message();
+ await saveChatConditional();
+
+ if (refresh == 'all') {
+ await reloadCurrentChat();
+ } else {
+ await update_partial_html(should_update_swipe);
+ }
+
+ console.log(
+ `[Amily助手] 设置第 ${message_id} 楼消息, 选项: ${JSON.stringify({
+ swipe_id,
+ refresh,
+ })}, 设置前使用的消息页: ${swipe_id_previous_index}, 设置的消息页: ${swipe_id_to_set_index}, 现在使用的消息页: ${swipe_id_to_use_index}`
+ );
+ }
+
+
+ async createChatMessages(chat_messages, options = {}) {
+ const { insert_at = 'end', refresh = 'all' } = options;
+
+ let insertIndex = insert_at;
+ if (insert_at !== 'end') {
+ insertIndex = insert_at < 0 ? chat.length + insert_at : insert_at;
+ if (insertIndex < 0 || insertIndex > chat.length) {
+ throw new Error(`无效的插入位置: ${insert_at}`);
+ }
+ }
+
+ const newMessages = chat_messages.map(msg => ({
+ name: msg.name ?? (msg.role === 'user' ? name1 : name2),
+ is_user: msg.role === 'user',
+ is_system: msg.is_hidden ?? false,
+ mes: msg.message,
+ variables: [msg.data ?? {}]
+ }));
+
+ if (insertIndex === 'end') {
+ chat.push(...newMessages);
+ } else {
+ chat.splice(insertIndex, 0, ...newMessages);
+ }
+
+ await saveChatConditional();
+
+ if (refresh === 'affected' && insertIndex === 'end') {
+ newMessages.forEach(msg => addOneMessage(msg));
+ } else if (refresh === 'all') {
+ await reloadCurrentChat();
+ }
+
+ console.log(`[Amily助手] 已创建 ${chat_messages.length} 条消息`);
+ }
+
+ async deleteChatMessages(message_ids, options = {}) {
+ const { refresh = 'all' } = options;
+
+ const validIds = message_ids
+ .map(id => id < 0 ? chat.length + id : id)
+ .filter(id => id >= 0 && id < chat.length)
+ .sort((a, b) => b - a); // 从后往前删除
+
+ for (const id of validIds) {
+ chat.splice(id, 1);
+ }
+
+ await saveChatConditional();
+
+ if (refresh === 'all') {
+ await reloadCurrentChat();
+ }
+
+ console.log(`[Amily助手] 已删除消息: ${validIds.join(', ')}`);
+ }
+
+ async getLorebooks() {
+ return [...world_names];
+ }
+
+ async getCharLorebooks(options = { type: 'all' }) {
+ try {
+ const context = getContext();
+ if (!context || context.characterId === undefined) {
+ console.warn('[Amily助手] 无法获取当前角色上下文');
+ return { primary: null, additional: [] };
+ }
+ const character = characters[context.characterId];
+ const primary = character?.data?.extensions?.world;
+ return { primary: primary || null, additional: [] };
+ } catch (error) {
+ console.error('[Amily助手] 获取角色世界书时出错:', error);
+ return { primary: null, additional: [] };
+ }
+ }
+
+ async getLorebookEntries(bookName) {
+ try {
+ const bookData = await loadWorldInfo(bookName);
+ if (!bookData || !bookData.entries) {
+ return [];
+ }
+ const positionMap = {
+ 0: 'before_character_definition',
+ 1: 'after_character_definition',
+ 2: 'before_author_note',
+ 3: 'after_author_note',
+ 4: 'at_depth_as_system'
+ };
+ return Object.entries(bookData.entries).map(([uid, entry]) => ({
+ uid: parseInt(uid),
+ comment: entry.comment || '无标题条目',
+ content: entry.content || '',
+ key: entry.key || [],
+ keys: entry.key || [],
+ enabled: !entry.disable,
+ constant: entry.constant || false,
+ position: positionMap[entry.position] || 'at_depth_as_system',
+ depth: entry.depth || 998,
+ }));
+ } catch (error) {
+ console.error(`[Amily助手] 获取世界书《${bookName}》条目时出错:`, error);
+ return [];
+ }
+ }
+
+ async setLorebookEntries(bookName, entries) {
+ try {
+ const bookData = await loadWorldInfo(bookName);
+ if (!bookData) {
+ console.error(`[Amily助手] 更新失败:找不到世界书《${bookName}》`);
+ return false;
+ }
+ for (const entryUpdate of entries) {
+ const existingEntry = bookData.entries[entryUpdate.uid];
+ if (existingEntry) {
+ if (entryUpdate.content !== undefined) existingEntry.content = entryUpdate.content;
+ if (entryUpdate.enabled !== undefined) existingEntry.disable = !entryUpdate.enabled;
+ if (entryUpdate.comment !== undefined) existingEntry.comment = entryUpdate.comment;
+ if (entryUpdate.key !== undefined) existingEntry.key = entryUpdate.key;
+ if (entryUpdate.keys !== undefined) existingEntry.key = entryUpdate.keys;
+ if (entryUpdate.constant !== undefined) existingEntry.constant = entryUpdate.constant;
+ if (entryUpdate.type === 'constant') existingEntry.constant = true;
+ if (entryUpdate.type === 'selective') existingEntry.constant = false;
+ if (entryUpdate.position !== undefined) {
+ const positionMap = {
+ 'before_character_definition': 0,
+ 'after_character_definition': 1,
+ 'before_author_note': 2,
+ 'after_author_note': 3,
+ 'at_depth': 4,
+ 'at_depth_as_system': 4
+ };
+ existingEntry.position = positionMap[entryUpdate.position] ?? 4;
+ }
+ if (entryUpdate.depth !== undefined) existingEntry.depth = entryUpdate.depth;
+ }
+ }
+ await saveWorldInfo(bookName, bookData, true);
+ reloadEditor(bookName);
+ eventSource.emit(event_types.WORLD_INFO_UPDATED, bookName);
+ return true;
+ } catch (error) {
+ console.error(`[Amily助手] 更新世界书《${bookName}》条目时出错:`, error);
+ return false;
+ }
+ }
+
+ async createLorebookEntries(bookName, entries) {
+ try {
+ let bookData = await loadWorldInfo(bookName);
+ if (!bookData) {
+ console.warn(`[Amily助手] 世界书《${bookName}》不存在,将自动创建`);
+ await this.createLorebook(bookName);
+ bookData = await loadWorldInfo(bookName);
+ if (!bookData) {
+ throw new Error(`创建并加载世界书《${bookName}》失败`);
+ }
+ }
+
+ for (const newEntryData of entries) {
+ const newEntry = createWorldInfoEntry(bookName, bookData);
+ const positionMap = {
+ 'before_character_definition': 0,
+ 'after_character_definition': 1,
+ 'before_author_note': 2,
+ 'after_author_note': 3,
+ 'at_depth': 4,
+ 'at_depth_as_system': 4
+ };
+ Object.assign(newEntry, {
+ comment: newEntryData.comment || '新条目',
+ content: newEntryData.content || '',
+ key: newEntryData.keys || newEntryData.key || [],
+ constant: newEntryData.type === 'constant' ? true : (newEntryData.constant || false),
+ position: typeof newEntryData.position === 'string' ? (positionMap[newEntryData.position] ?? 4) : (newEntryData.position ?? 4),
+ depth: newEntryData.depth ?? 998,
+ disable: !(newEntryData.enabled ?? true),
+ });
+ if (newEntryData.type === 'selective') newEntry.constant = false;
+ }
+ await saveWorldInfo(bookName, bookData, true);
+ reloadEditor(bookName);
+ return true;
+ } catch (error) {
+ console.error(`[Amily助手] 在世界书《${bookName}》中创建新条目时出错:`, error);
+ return false;
+ }
+ }
+
+ async createLorebook(bookName) {
+ try {
+ if (world_names.includes(bookName)) {
+ console.warn(`[Amily助手] 创建失败:世界书《${bookName}》已存在`);
+ return false;
+ }
+ await createNewWorldInfo(bookName);
+ if (!world_names.includes(bookName)) {
+ world_names.push(bookName);
+ world_names.sort();
+ }
+ document.dispatchEvent(new CustomEvent('amily-lorebook-created', { detail: { bookName } }));
+ return true;
+ } catch (error) {
+ console.error(`[Amily助手] 创建世界书《${bookName}》时出错:`, error);
+ return false;
+ }
+ }
+
+ // ==================== 斜杠命令相关 ====================
+
+ async triggerSlash(command) {
+ try {
+ console.log(`[Amily助手] 正在执行斜杠命令: ${command}`);
+ const result = await executeSlashCommandsWithOptions(command);
+ if (result.isError) {
+ throw new Error(result.errorMessage);
+ }
+ return result.pipe;
+ } catch (error) {
+ console.error(`[Amily助手] 执行斜杠命令 '${command}' 时出错:`, error);
+ throw error;
+ }
+ }
+
+ // ==================== 工具方法 ====================
+
+ async loadWorldInfo(bookName) {
+ return await loadWorldInfo(bookName);
+ }
+
+ async saveWorldInfo(bookName, data, isWorldInfo) {
+ await saveWorldInfo(bookName, data, isWorldInfo);
+ }
+
+ getLastMessageId() {
+ return chat.length - 1;
+ }
+}
+
+export const amilyHelper = new AmilyHelper();
+
+
+export function initializeAmilyHelper() {
+ if (!window.AmilyHelper) {
+ window.AmilyHelper = amilyHelper;
+ console.log('[Amily2] AmilyHelper 已成功初始化并附加到 window 对象');
+ }
+}
+
+// ==================== iframe 通信 API ====================
+
+
+export function makeRequest(request, data) {
+ return new Promise((resolve, reject) => {
+ const uid = Date.now() + Math.random();
+ const callbackRequest = `${request}_callback`;
+
+ function handleMessage(event) {
+ const msgData = event.data || {};
+ if (msgData.request === callbackRequest && msgData.uid === uid) {
+ window.removeEventListener('message', handleMessage);
+ if (msgData.error) {
+ reject(new Error(msgData.error));
+ } else {
+ resolve(msgData.result);
+ }
+ }
+ }
+
+ window.addEventListener('message', handleMessage);
+
+ setTimeout(() => {
+ window.removeEventListener('message', handleMessage);
+ reject(new Error(`请求 '${request}' 超时 (30秒)`));
+ }, 30000);
+
+ window.parent.postMessage({
+ source: 'amily2-iframe-request',
+ request: request,
+ uid: uid,
+ data: data
+ }, '*');
+ });
+}
+
+// ==================== 主窗口 API ====================
+
+const apiHandlers = new Map();
+
+
+export function registerApiHandler(request, handler) {
+ if (apiHandlers.has(request)) {
+ console.warn(`[Amily2-IframeAPI] 覆盖请求处理器: ${request}`);
+ }
+ apiHandlers.set(request, handler);
+}
+
+
+export function initializeApiListener() {
+ window.addEventListener('message', async (event) => {
+ const data = event.data || {};
+ if (data.source !== 'amily2-iframe-request' || !data.request || data.uid === undefined) {
+ return;
+ }
+
+ const handler = apiHandlers.get(data.request);
+ const callbackRequest = `${data.request}_callback`;
+
+ if (!handler) {
+ console.error(`[Amily2-IframeAPI] 收到未知请求: ${data.request}`);
+ event.source.postMessage({
+ request: callbackRequest,
+ uid: data.uid,
+ error: `未注册请求 '${data.request}' 的处理器`
+ }, '*');
+ return;
+ }
+
+ try {
+ const result = await handler(data.data, event);
+ event.source.postMessage({
+ request: callbackRequest,
+ uid: data.uid,
+ result: result
+ }, '*');
+ } catch (error) {
+ console.error(`[Amily2-IframeAPI] 执行处理器 '${data.request}' 时出错:`, error);
+ event.source.postMessage({
+ request: callbackRequest,
+ uid: data.uid,
+ error: error.message || String(error)
+ }, '*');
+ }
+ });
+ console.log('[Amily2-IframeAPI] 主窗口监听器已初始化');
+}
diff --git a/core/tavern-helper/renderer-bindings.js b/core/tavern-helper/renderer-bindings.js
new file mode 100644
index 0000000..02b1e50
--- /dev/null
+++ b/core/tavern-helper/renderer-bindings.js
@@ -0,0 +1,51 @@
+import { renderAllIframes, clearAllIframes, initializeRenderer } from './renderer.js';
+import { extension_settings } from "/scripts/extensions.js";
+import { extensionName } from "../../utils/settings.js";
+import { saveSettingsDebounced } from "/script.js";
+
+let isRendererInitialized = false;
+
+export function initializeRendererBindings() {
+ const container = $("#amily2_drawer_content").length
+ ? $("#amily2_drawer_content")
+ : $("#amily2_chat_optimiser");
+
+ if (!container.length) {
+ console.warn("[Amily2-Renderer] Could not find the settings container.");
+ return;
+ }
+ container.on('change', '#render-enable-toggle', function() {
+ const isChecked = this.checked;
+
+ if (!extension_settings[extensionName]) {
+ extension_settings[extensionName] = {};
+ }
+ extension_settings[extensionName].render_enabled = isChecked;
+ saveSettingsDebounced();
+
+ if (isChecked && !isRendererInitialized) {
+ initializeRenderer();
+ isRendererInitialized = true;
+ console.log("[Amily2-Renderer] Renderer has been initialized on-demand.");
+ }
+
+ if (isChecked) {
+ renderAllIframes();
+ } else {
+ clearAllIframes();
+ }
+ });
+
+ container.on('change', '#render-depth', function() {
+ const depth = parseInt(this.value, 10);
+ if (!extension_settings[extensionName]) {
+ extension_settings[extensionName] = {};
+ }
+ extension_settings[extensionName].render_depth = depth;
+ saveSettingsDebounced();
+
+ toastr.success(`渲染深度已保存为: ${depth}`);
+ });
+
+ console.log("[Amily2-Renderer] Renderer UI events have been successfully bound.");
+}
diff --git a/core/tavern-helper/renderer.html b/core/tavern-helper/renderer.html
new file mode 100644
index 0000000..96540fa
--- /dev/null
+++ b/core/tavern-helper/renderer.html
@@ -0,0 +1,21 @@
+
+
+
+
+
启用前端渲染
+
在聊天消息中渲染HTML内容。
+
+
+
+
渲染深度
+
设置要渲染的最新消息的数量。0表示无限制。
+
+
+
+
“想给温柔的人奏响一段温柔的小插曲。”
+
+ 当开启Amily前端渲染后,务必关闭酒馆助手的前端渲染,借鉴了酒馆助手的渲染和交互逻辑,实现了更加轻量级,渲染更快,降低卡顿。
+
+ 与酒馆助手的脚本、变量等功能,完全无冲突,可并存使用。
+
+
diff --git a/core/tavern-helper/renderer.js b/core/tavern-helper/renderer.js
new file mode 100644
index 0000000..c615d35
--- /dev/null
+++ b/core/tavern-helper/renderer.js
@@ -0,0 +1,606 @@
+import { eventSource, event_types } from '/script.js';
+import { extension_settings } from '/scripts/extensions.js';
+import { extensionName } from '../../utils/settings.js';
+
+const settings = {
+ sandboxMode: false,
+ useBlob: false,
+ wrapperIframe: true,
+ renderEnabled: true
+};
+
+const winMap = new Map();
+let lastHeights = new WeakMap();
+const blobUrls = new WeakMap();
+const hashToBlobUrl = new Map();
+const blobLRU = [];
+const BLOB_CACHE_LIMIT = 32;
+
+function generateUniqueId() {
+ return `amily2-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
+}
+
+function shouldRenderContentByBlock(codeBlock) {
+ if (!codeBlock) return false;
+ const content = (codeBlock.textContent || '').trim();
+ if (!content) return false;
+ return /^\s*>> 0).toString(16);
+}
+
+function buildResourceHints(html) {
+ const urls = Array.from(new Set((html.match(/https?:\/\/[^"'()\s]+/gi) || []).map(u => { try { return new URL(u).origin } catch { return null } }).filter(Boolean)));
+ let hints = "";
+ const maxHosts = 6;
+ for (let i = 0; i < Math.min(urls.length, maxHosts); i++) {
+ const origin = urls[i];
+ hints += ``;
+ hints += ``;
+ }
+ let preload = "";
+ const font = (html.match(/https?:\/\/[^"'()\s]+\.(?:woff2|woff|ttf|otf)/i) || [])[0];
+ if (font) {
+ const type = font.endsWith(".woff2") ? "font/woff2" : font.endsWith(".woff") ? "font/woff" : font.endsWith(".ttf") ? "font/ttf" : "font/otf";
+ preload += ``;
+ }
+ const css = (html.match(/https?:\/\/[^"'()\s]+\.css/i) || [])[0];
+ if (css) {
+ preload += ``;
+ }
+ const img = (html.match(/https?:\/\/[^"'()\s]+\.(?:png|jpg|jpeg|webp|gif|svg)/i) || [])[0];
+ if (img) {
+ preload += ``;
+ }
+ return hints + preload;
+}
+
+function iframeClientScript() {
+ return `
+(function(){
+ function measureVisibleHeight(){
+ try{
+ var doc = document;
+ var target = doc.querySelector('.calendar-wrapper') || doc.body;
+ if(!target) return 0;
+ var minTop = Infinity, maxBottom = 0;
+ var addRect = function(el){
+ try{
+ var r = el.getBoundingClientRect();
+ if(r && r.height > 0){
+ if(minTop > r.top) minTop = r.top;
+ if(maxBottom < r.bottom) maxBottom = r.bottom;
+ }
+ }catch(e){}
+ };
+ addRect(target);
+ var children = target.children || [];
+ for(var i=0;i 0 ? Math.ceil(maxBottom - Math.min(minTop, 0)) : (target.scrollHeight || 0);
+ }catch(e){
+ return (document.body && document.body.scrollHeight) || 0;
+ }
+ } function post(m){ try{ parent.postMessage(m,'*') }catch(e){} }
+ var rafPending=false, lastH=0;
+ var HYSTERESIS = 2;
+ function send(force){
+ if(rafPending && !force) return;
+ rafPending = true;
+ requestAnimationFrame(function(){
+ rafPending = false;
+ var h = measureVisibleHeight();
+ if(force || Math.abs(h - lastH) >= HYSTERESIS){
+ lastH = h;
+ post({height:h, force:!!force});
+ }
+ });
+ }
+ try{ send(true) }catch(e){}
+ document.addEventListener('DOMContentLoaded', function(){ send(true) }, {once:true});
+ window.addEventListener('load', function(){ send(true) }, {once:true});
+ try{
+ if(document.fonts){
+ document.fonts.ready.then(function(){ send(true) }).catch(function(){});
+ if(document.fonts.addEventListener){
+ document.fonts.addEventListener('loadingdone', function(){ send(true) });
+ document.fonts.addEventListener('loadingerror', function(){ send(true) });
+ }
+ }
+ }catch(e){}
+ ['transitionend','animationend'].forEach(function(evt){
+ document.addEventListener(evt, function(){ send(false) }, {passive:true, capture:true});
+ });
+ try{
+ var root = document.querySelector('.calendar-wrapper') || document.body || document.documentElement;
+ var ro = new ResizeObserver(function(){ send(false) });
+ ro.observe(root);
+ }catch(e){
+ try{
+ var rootMO = document.querySelector('.calendar-wrapper') || document.body || document.documentElement;
+ new MutationObserver(function(){ send(false) })
+ .observe(rootMO, {childList:true, subtree:true, attributes:true, characterData:true});
+ }catch(e){}
+ window.addEventListener('resize', function(){ send(false) }, {passive:true});
+ }
+ window.addEventListener('message', function(e){
+ var d = e && e.data || {};
+ if(d && d.type === 'probe') setTimeout(function(){ send(true) }, 10);
+ });
+})();`;
+}
+
+function buildWrappedHtml(html) {
+ const origin = (typeof location !== 'undefined' && location.origin) ? location.origin : '';
+ const baseTag = settings && settings.useBlob ? `` : "";
+ const headHints = buildResourceHints(html);
+ const vhFix = ``;
+
+ const apiScript = `
+
+
+`;
+
+ const injectionBlock = `
+${baseTag}
+
+${headHints}
+${vhFix}
+${apiScript}
+`;
+
+ const isFullHtml = //i.test(html);
+
+ if (isFullHtml) {
+ if (html.includes('')) {
+ return html.replace('', `${injectionBlock}`);
+ } else if (html.includes('${injectionBlock}${injectionBlock}${html}`;
+ }
+
+ return `
+
+
+
+
+
+
+${injectionBlock}
+
+${html}`;
+}
+
+
+function getOrCreateWrapper(preEl) {
+ let wrapper = preEl.previousElementSibling;
+ if (!wrapper || !wrapper.classList.contains('amily2-iframe-wrapper')) {
+ wrapper = document.createElement('div');
+ wrapper.className = 'amily2-iframe-wrapper';
+ wrapper.style.cssText = 'margin:0;';
+ preEl.parentNode.insertBefore(wrapper, preEl);
+ }
+ return wrapper;
+}
+
+function registerIframeMapping(iframe, wrapper) {
+ const tryMap = () => {
+ try {
+ if (iframe && iframe.contentWindow) {
+ winMap.set(iframe.contentWindow, { iframe, wrapper });
+ return true;
+ }
+ } catch (e) { }
+ return false;
+ };
+ if (tryMap()) return;
+ let tries = 0;
+ const t = setInterval(() => {
+ tries++;
+ if (tryMap() || tries > 20) clearInterval(t);
+ }, 25);
+}
+
+function handleIframeMessage(event) {
+ const data = event.data || {};
+ let rec = winMap.get(event.source);
+ if (!rec || !rec.iframe) {
+ const iframes = document.querySelectorAll('iframe.amily2-iframe');
+ for (const iframe of iframes) {
+ if (iframe.contentWindow === event.source) {
+ rec = { iframe, wrapper: iframe.parentElement };
+ winMap.set(event.source, rec);
+ break;
+ }
+ }
+ }
+ if (rec && rec.iframe && typeof data.height === 'number') {
+ const next = Math.max(0, Number(data.height) || 0);
+ if (next < 1) return;
+ const prev = lastHeights.get(rec.iframe) || 0;
+ if (!data.force && Math.abs(next - prev) < 1) return;
+ lastHeights.set(rec.iframe, next);
+ requestAnimationFrame(() => { rec.iframe.style.height = `${next}px`; });
+ }
+}
+
+function setIframeBlobHTML(iframe, fullHTML, codeHash) {
+ const existing = hashToBlobUrl.get(codeHash);
+ if (existing) {
+ iframe.src = existing;
+ blobUrls.set(iframe, existing);
+ return;
+ }
+ const blob = new Blob([fullHTML], { type: 'text/html' });
+ const url = URL.createObjectURL(blob);
+ iframe.src = url;
+ blobUrls.set(iframe, url);
+ hashToBlobUrl.set(codeHash, url);
+ blobLRU.push(codeHash);
+ while (blobLRU.length > BLOB_CACHE_LIMIT) {
+ const old = blobLRU.shift();
+ const u = hashToBlobUrl.get(old);
+ hashToBlobUrl.delete(old);
+ try { URL.revokeObjectURL(u) } catch (e) { }
+ }
+}
+
+function releaseIframeBlob(iframe) {
+ try {
+ const url = blobUrls.get(iframe);
+ if (url) URL.revokeObjectURL(url);
+ blobUrls.delete(iframe);
+ } catch (e) { }
+}
+
+function renderHtmlInIframe(htmlContent, container, preElement) {
+ try {
+ const originalHash = djb2(htmlContent);
+ const iframe = document.createElement('iframe');
+ iframe.id = generateUniqueId();
+ iframe.className = 'amily2-iframe';
+ iframe.style.cssText = 'width:100%;border:none;background:transparent;overflow:hidden;height:0;margin:0;padding:0;display:block;contain:layout paint style;will-change:height;min-height:50px';
+ iframe.setAttribute('frameborder', '0');
+ iframe.setAttribute('scrolling', 'no');
+ iframe.loading = 'eager';
+ if (settings.sandboxMode) {
+ iframe.setAttribute('sandbox', 'allow-scripts allow-modals');
+ } else {
+ iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-modals allow-popups');
+ }
+ const wrapper = getOrCreateWrapper(preElement);
+ wrapper.querySelectorAll('.amily2-iframe').forEach(old => {
+ try { old.src = 'about:blank'; } catch (e) { }
+ releaseIframeBlob(old);
+ old.remove();
+ });
+ const codeHash = djb2(htmlContent);
+ const full = buildWrappedHtml(htmlContent);
+ if (settings.useBlob) {
+ setIframeBlobHTML(iframe, full, codeHash);
+ } else {
+ iframe.srcdoc = full;
+ }
+ wrapper.appendChild(iframe);
+ preElement.classList.remove('amily2-show');
+ preElement.style.display = 'none';
+ registerIframeMapping(iframe, wrapper);
+ try { iframe.contentWindow?.postMessage({ type: 'probe' }, '*'); } catch (e) { }
+ preElement.dataset.amily2Final = 'true';
+ preElement.dataset.amily2Hash = originalHash;
+ return iframe;
+ } catch (err) {
+ return null;
+ }
+}
+
+function processCodeBlocks(messageElement) {
+ if (extension_settings[extensionName].render_enabled === false) return;
+ try {
+ const codeBlocks = messageElement.querySelectorAll('pre > code');
+ codeBlocks.forEach(codeBlock => {
+ const preElement = codeBlock.parentElement;
+ const should = shouldRenderContentByBlock(codeBlock);
+ const html = codeBlock.textContent || '';
+ const hash = djb2(html);
+ const isFinal = preElement.dataset.amily2Final === 'true';
+ const same = preElement.dataset.amily2Hash === hash;
+ if (isFinal && same) return;
+ if (should) {
+ renderHtmlInIframe(html, preElement.parentNode, preElement);
+ } else {
+ preElement.classList.add('amily2-show');
+ preElement.removeAttribute('data-amily2-final');
+ preElement.removeAttribute('data-amily2-hash');
+ preElement.style.display = '';
+ }
+ preElement.dataset.amily2Bound = 'true';
+ });
+ } catch (err) {
+ console.error('[Amily2-Renderer] Error during processCodeBlocks:', err);
+ }
+}
+
+function processMessageById(messageId) {
+ const messageElement = document.querySelector(`div.mes[mesid="${messageId}"] .mes_text`);
+ if (!messageElement) return;
+ processCodeBlocks(messageElement);
+}
+
+export function initializeRenderer() {
+ if (window.isXiaobaixEnabled) {
+ console.log('[Amily2-Renderer] 检测到 LittleWhiteBox 已激活,为避免冲突,Amily2 渲染器已禁用。');
+ return;
+ }
+
+ const handleMessage = (data) => {
+ const messageId = typeof data === 'object' ? data.messageId : data;
+ if (messageId == null) return;
+ console.log('[Amily2-Renderer] 处理消息渲染:', messageId);
+ setTimeout(() => processMessageById(messageId), 50);
+ };
+
+ eventSource.on(event_types.MESSAGE_RECEIVED, handleMessage);
+ eventSource.on(event_types.MESSAGE_UPDATED, handleMessage);
+ eventSource.on(event_types.MESSAGE_SWIPED, handleMessage);
+ eventSource.on(event_types.MESSAGE_EDITED, handleMessage);
+ eventSource.on(event_types.USER_MESSAGE_RENDERED, handleMessage);
+ eventSource.on(event_types.CHARACTER_MESSAGE_RENDERED, handleMessage);
+ eventSource.on(event_types.IMPERSONATE_READY, handleMessage);
+
+ eventSource.on(event_types.CHAT_CHANGED, () => {
+ console.log('[Amily2-Renderer] 聊天已切换,重新渲染所有 iframe');
+ setTimeout(renderAllIframes, 100);
+ });
+
+ window.addEventListener('message', handleIframeMessage);
+
+ console.log('[Amily2-Renderer] 渲染器已初始化,监听事件: MESSAGE_RECEIVED, MESSAGE_UPDATED, MESSAGE_SWIPED, MESSAGE_EDITED, USER_MESSAGE_RENDERED, CHARACTER_MESSAGE_RENDERED, IMPERSONATE_READY');
+}
+
+export function renderAllIframes() {
+ const messages = document.querySelectorAll('.mes');
+ messages.forEach(message => {
+ const messageId = message.getAttribute('mesid');
+ if (messageId) {
+ processMessageById(messageId);
+ }
+ });
+}
+
+export function clearAllIframes() {
+ const iframes = document.querySelectorAll('.amily2-iframe');
+ iframes.forEach(iframe => {
+ const wrapper = iframe.parentElement;
+ if (wrapper && wrapper.classList.contains('amily2-iframe-wrapper')) {
+ const preElement = wrapper.nextElementSibling;
+ if (preElement && preElement.tagName === 'PRE') {
+ preElement.classList.add('amily2-show');
+ preElement.style.display = '';
+ }
+ wrapper.remove();
+ }
+ });
+}
diff --git a/core/tavernhelper-compatibility.js b/core/tavernhelper-compatibility.js
index cd7180d..0205809 100644
--- a/core/tavernhelper-compatibility.js
+++ b/core/tavernhelper-compatibility.js
@@ -1,9 +1,17 @@
import { amilyHelper } from './tavern-helper/main.js';
-import { eventSource, event_types } from "/script.js";
+import {
+ world_names,
+ loadWorldInfo,
+ createNewWorldInfo,
+ createWorldInfoEntry,
+ saveWorldInfo,
+ reloadEditor
+} from "/scripts/world-info.js";
+import { refreshWorldbookListOnly } from './lore.js';
-// 我们现在总是“可用”的,因为我们依赖自己的实现,而不是那个屎山酒馆。
+// 检查我们自己的 amilyHelper 是否存在
export function isTavernHelperAvailable() {
- return true;
+ return typeof amilyHelper !== 'undefined' && amilyHelper !== null;
}
export async function compatibleTriggerSlash(command) {
return await amilyHelper.triggerSlash(command);
@@ -27,43 +35,96 @@ export async function safeUpdateLorebookEntries(bookName, entries) {
export async function compatibleWriteToLorebook(targetLorebookName, entryComment, contentUpdateCallback, options = {}) {
- console.log('[Amily助手-写入模块] 接收到的写入选项:', options);
+ console.log('[兼容写入模块] 接收到的写入选项:', options);
+ // 优先使用 AmilyHelper
+ if (isTavernHelperAvailable()) {
+ try {
+ console.log('[兼容写入模块] 检测到 AmilyHelper,优先使用新逻辑...');
+ const entries = await amilyHelper.getLorebookEntries(targetLorebookName);
+ const existingEntry = entries.find((e) => e.comment === entryComment && e.enabled);
+
+ if (existingEntry) {
+ const newContent = contentUpdateCallback(existingEntry.content);
+ await amilyHelper.setLorebookEntries(targetLorebookName, [{ uid: existingEntry.uid, content: newContent }]);
+ } else {
+ const newContent = contentUpdateCallback(null);
+ const { keys = [], isConstant = false, insertion_position, depth: insertion_depth } = options;
+ const positionMap = { 'before_char': 0, 'after_char': 1, 'before_an': 2, 'after_an': 3, 'at_depth': 4 };
+
+ const newEntryData = {
+ comment: entryComment,
+ content: newContent,
+ key: keys,
+ constant: isConstant,
+ position: positionMap[insertion_position] ?? 4,
+ depth: parseInt(insertion_depth) || 998,
+ enabled: true,
+ };
+ await amilyHelper.createLorebookEntries(targetLorebookName, [newEntryData]);
+ }
+ console.log(`[Amily助手] 成功将条目 "${entryComment}" 写入《${targetLorebookName}》。`);
+
+ // 派发被证明有效的自定义刷新事件
+ document.dispatchEvent(new CustomEvent('amily-lorebook-created', { detail: { bookName: targetLorebookName } }));
+ refreshWorldbookListOnly(); // 刷新UI
+ return true;
+ } catch (error) {
+ console.error(`[Amily助手] 写入失败,将尝试回退到传统逻辑。错误:`, error);
+ toastr.warning('Amily助手写入失败,尝试使用传统方式...', '兼容模式');
+ }
+ }
+
+ // AmilyHelper 不可用或失败时的后备传统逻辑
try {
- const entries = await amilyHelper.getLorebookEntries(targetLorebookName);
- const existingEntry = entries.find((e) => e.comment === entryComment && e.enabled);
+ console.log('[兼容写入模块] AmilyHelper 不可用或失败,使用传统逻辑...');
+ let bookData = await loadWorldInfo(targetLorebookName);
+
+ if (!bookData) {
+ console.warn(`[传统逻辑] 世界书《${targetLorebookName}》不存在,将自动创建。`);
+ await createNewWorldInfo(targetLorebookName);
+ if (!world_names.includes(targetLorebookName)) {
+ world_names.push(targetLorebookName);
+ world_names.sort();
+ refreshWorldbookListOnly(); // 刷新UI
+ }
+ document.dispatchEvent(new CustomEvent('amily-lorebook-created', { detail: { bookName: targetLorebookName } }));
+ bookData = await loadWorldInfo(targetLorebookName);
+ if (!bookData) throw new Error(`创建并加载世界书《${targetLorebookName}》失败。`);
+ }
+
+ const existingEntry = Object.values(bookData.entries).find(e => e.comment === entryComment && !e.disable);
if (existingEntry) {
- const newContent = contentUpdateCallback(existingEntry.content);
- await amilyHelper.setLorebookEntries(targetLorebookName, [{ uid: existingEntry.uid, content: newContent }]);
+ existingEntry.content = contentUpdateCallback(existingEntry.content);
} else {
- const newContent = contentUpdateCallback(null);
+ const newEntry = createWorldInfoEntry(targetLorebookName, bookData);
const { keys = [], isConstant = false, insertion_position, depth: insertion_depth } = options;
-
const positionMap = { 'before_char': 0, 'after_char': 1, 'before_an': 2, 'after_an': 3, 'at_depth': 4 };
-
- const newEntryData = {
+
+ Object.assign(newEntry, {
comment: entryComment,
- content: newContent,
+ content: contentUpdateCallback(null),
key: keys,
constant: isConstant,
position: positionMap[insertion_position] ?? 4,
depth: parseInt(insertion_depth) || 998,
- enabled: true,
- };
-
- await amilyHelper.createLorebookEntries(targetLorebookName, [newEntryData]);
+ disable: false,
+ });
}
- if (eventSource && typeof eventSource.emit === "function" && event_types.CHARACTER_PAGE_LOADED) {
- eventSource.emit(event_types.CHARACTER_PAGE_LOADED);
- }
+ await saveWorldInfo(targetLorebookName, bookData, true);
+ console.log(`[传统逻辑] 成功将条目 "${entryComment}" 写入《${targetLorebookName}》。`);
- console.log(`[Amily助手] 成功将条目 "${entryComment}" 写入《${targetLorebookName}》。`);
+ // 刷新编辑器(如果正在查看)
+ reloadEditor(targetLorebookName);
+
+ // 派发被证明有效的自定义刷新事件
+ document.dispatchEvent(new CustomEvent('amily-lorebook-created', { detail: { bookName: targetLorebookName } }));
return true;
} catch (error) {
- console.error(`[Amily助手] 写入世界书时发生严重错误:`, error);
- toastr.error(`写入世界书失败: ${error.message}`, "Amily助手");
+ console.error(`[传统逻辑] 写入世界书时发生严重错误:`, error);
+ toastr.error(`写入世界书失败: ${error.message}`, "传统逻辑");
return false;
}
}
diff --git a/glossary/GT_bindings.js b/glossary/GT_bindings.js
index f9e4708..24452f7 100644
--- a/glossary/GT_bindings.js
+++ b/glossary/GT_bindings.js
@@ -659,8 +659,9 @@ export function bindGlossaryEvents() {
bindReorganizeEvents();
loadWorldBooks();
- eventSource.on(event_types.CHARACTER_PAGE_LOADED, () => {
- console.log('[Amily2-术语表] 检测到角色加载,重新加载世界书列表以确保同步。');
+ // 监听我们自己的世界书创建事件,而不是监听全局的角色加载事件,避免冲突
+ document.addEventListener('amily-lorebook-created', (event) => {
+ console.log(`[Amily2-术语表] 检测到新世界书《${event.detail.bookName}》创建,重新加载列表以确保同步。`);
loadWorldBooks();
});
diff --git a/index.js b/index.js
index a9c2597..6acf441 100644
--- a/index.js
+++ b/index.js
@@ -11,6 +11,7 @@ import { characters, this_chid } from '/script.js';
import { injectTableData, generateTableContent } from "./core/table-system/injector.js";
import { initialize as initializeRagProcessor } from "./core/rag-processor.js";
import { loadTables, clearHighlights, rollbackAndRefill, rollbackState, commitPendingDeletions, saveStateToMessage, getMemoryState, clearUpdatedTables } from './core/table-system/manager.js';
+import { fillWithSecondaryApi } from './core/table-system/secondary-filler.js';
import { renderTables } from './ui/table-bindings.js';
import { log } from './core/table-system/logger.js';
import { eventSource, event_types, saveSettingsDebounced } from '/script.js';
@@ -25,7 +26,8 @@ import { cwbDefaultSettings } from './CharacterWorldBook/src/cwb_config.js';
import { bindGlossaryEvents } from './glossary/GT_bindings.js';
import './core/amily2-updater.js';
import { updateOrInsertTableInChat, startContinuousRendering, stopContinuousRendering } from './ui/message-table-renderer.js';
-import { isTavernHelperAvailable } from './core/tavernhelper-compatibility.js';
+import { initializeRenderer } from './core/tavern-helper/renderer.js';
+import { initializeApiListener, registerApiHandler, amilyHelper, initializeAmilyHelper } from './core/tavern-helper/main.js';
const STYLE_SETTINGS_KEY = 'amily2_custom_styles';
const STYLE_ROOT_SELECTOR = '#amily2_memorisation_forms_panel';
@@ -226,6 +228,8 @@ function loadPluginStyles() {
loadStyleFile("amily2-glossary.css"); // 【新圣谕】为术语表披上其专属华服
loadStyleFile("table.css"); // 【第四道圣谕】为内存储司披上其专属华服
loadStyleFile("optimization.css"); // 【第五道圣谕】为剧情优化披上其专属华服
+ loadStyleFile("renderer.css"); // 【新圣谕】为渲染器披上其专属华服
+ loadStyleFile("iframe-renderer.css"); // 【新圣谕】为iframe渲染内容披上其专属华服
// 【第六道圣谕】为角色世界书披上其专属华服
const cwbStyleId = 'cwb-feature-style';
@@ -254,6 +258,59 @@ function loadPluginStyles() {
}
+window.addEventListener('message', function (event) {
+ // 处理头像获取请求
+ if (event.data && event.data.type === 'getAvatars') {
+ // 【兼容性修复】如果 LittleWhiteBox 激活,则不处理此消息,避免冲突
+ if (window.isXiaobaixEnabled) {
+ return;
+ }
+ const userAvatar = `/characters/${getContext().userCharacter?.avatar ?? ''}`;
+ const charAvatar = `/characters/${getContext().characters[this_chid]?.avatar ?? ''}`;
+ event.source.postMessage({
+ source: 'amily2-host',
+ type: 'avatars',
+ urls: { user: userAvatar, char: charAvatar }
+ }, '*');
+ return;
+ }
+
+ // 处理来自 iframe 的交互事件
+ if (event.data && event.data.source === 'amily2-iframe') {
+ const { action, detail } = event.data;
+ console.log(`[Amily2-主窗口] 收到来自iframe的动作: ${action}`, detail);
+
+ switch (action) {
+ case 'sendMessage':
+ if (detail && detail.message) {
+ $('#send_textarea').val(detail.message).trigger('input');
+ $('#send_but').trigger('click');
+ console.log(`[Amily2-主窗口] 已发送消息: ${detail.message}`);
+ }
+ break;
+
+ case 'showToast':
+ if (detail && detail.message && window.toastr) {
+ const toastType = detail.type || 'info';
+ if (typeof window.toastr[toastType] === 'function') {
+ window.toastr[toastType](detail.message, detail.title || '通知');
+ }
+ }
+ break;
+
+ case 'buttonClick':
+ console.log(`[Amily2-主窗口] 按钮被点击:`, detail);
+ if (window.toastr) {
+ window.toastr.info(`按钮 "${detail.buttonId || '未知'}" 被点击`, 'iframe交互');
+ }
+ break;
+
+ default:
+ console.warn(`[Amily2-主窗口] 未知的动作类型: ${action}`);
+ }
+ }
+});
+
window.addEventListener("error", (event) => {
const stackTrace = event.error?.stack || "";
if (stackTrace.includes("ST-Amily2-Chat-Optimisation")) {
@@ -264,12 +321,106 @@ window.addEventListener("error", (event) => {
jQuery(async () => {
+ console.log("[Amily2号-帝国枢密院] 开始执行开国大典...");
+ initializeApiListener();
+
+ registerApiHandler('getChatMessages', async (data) => {
+ return amilyHelper.getChatMessages(data.range, data.options);
+ });
+
+ registerApiHandler('setChatMessages', async (data) => {
+ return await amilyHelper.setChatMessages(data.messages, data.options);
+ });
+
+ registerApiHandler('setChatMessage', async (data) => {
+ const field_values = data.field_values || data.content;
+ const message_id = data.message_id !== undefined ? data.message_id : data.index;
+ const options = data.options || {};
+
+ console.log('[Amily2-API] setChatMessage 收到参数:', { field_values, message_id, options, raw_data: data });
+
+ return await amilyHelper.setChatMessage(field_values, message_id, options);
+ });
+
+ registerApiHandler('createChatMessages', async (data) => {
+ return await amilyHelper.createChatMessages(data.messages, data.options);
+ });
+
+ registerApiHandler('deleteChatMessages', async (data) => {
+ return await amilyHelper.deleteChatMessages(data.ids, data.options);
+ });
+
+ registerApiHandler('getLorebooks', async (data) => {
+ return await amilyHelper.getLorebooks();
+ });
+
+ registerApiHandler('getCharLorebooks', async (data) => {
+ return await amilyHelper.getCharLorebooks(data.options);
+ });
+
+ registerApiHandler('getLorebookEntries', async (data) => {
+ return await amilyHelper.getLorebookEntries(data.bookName);
+ });
+
+ registerApiHandler('setLorebookEntries', async (data) => {
+ return await amilyHelper.setLorebookEntries(data.bookName, data.entries);
+ });
+
+ registerApiHandler('createLorebookEntries', async (data) => {
+ return await amilyHelper.createLorebookEntries(data.bookName, data.entries);
+ });
+
+ registerApiHandler('createLorebook', async (data) => {
+ return await amilyHelper.createLorebook(data.bookName);
+ });
+
+ registerApiHandler('triggerSlash', async (data) => {
+ return await amilyHelper.triggerSlash(data.command);
+ });
+
+ registerApiHandler('getLastMessageId', async (data) => {
+ return amilyHelper.getLastMessageId();
+ });
+
+ registerApiHandler('toastr', async (data) => {
+ if (window.toastr && typeof window.toastr[data.type] === 'function') {
+ window.toastr[data.type](data.message, data.title);
+ }
+ return true;
+ });
+
+ registerApiHandler('switchSwipe', async (data) => {
+ const { messageIndex, swipeIndex } = data;
+ const messages = await amilyHelper.getChatMessages(messageIndex, { include_swipes: true });
+
+ if (messages && messages.length > 0 && messages[0].swipes) {
+ const content = messages[0].swipes[swipeIndex];
+ if (content !== undefined) {
+ await amilyHelper.setChatMessages([{
+ message_id: messageIndex,
+ message: content
+ }], { refresh: 'affected' });
+
+ const context = getContext();
+ if (context.chat[messageIndex]) {
+ context.chat[messageIndex].swipe_id = swipeIndex;
+ }
+
+ return { success: true, message: `已切换至开场白 ${swipeIndex}` };
+ }
+ }
+
+ throw new Error(`无法切换到开场白 ${swipeIndex}`);
+ });
+
+ initializeAmilyHelper();
+
console.log("[Amily2号-帝国枢密院] 开始执行开国大典...");
if (!extension_settings[extensionName]) {
extension_settings[extensionName] = {};
}
- const combinedDefaultSettings = { ...defaultSettings, ...tableSystemDefaultSettings, ...cwbDefaultSettings, render_on_every_message: false };
+ const combinedDefaultSettings = { ...defaultSettings, ...tableSystemDefaultSettings, ...cwbDefaultSettings, render_on_every_message: false, render_enabled: false };
for (const key in combinedDefaultSettings) {
if (extension_settings[extensionName][key] === undefined) {
@@ -298,7 +449,6 @@ jQuery(async () => {
console.log("[Amily2号-开国大典] 步骤三:开始召唤府邸...");
createDrawer();
- // 【V15.0 修复】为术语表面板添加轮询加载,确保在面板渲染后再绑定事件
function waitForGlossaryPanelAndBindEvents() {
let attempts = 0;
const maxAttempts = 50;
@@ -380,10 +530,8 @@ jQuery(async () => {
let isProcessingPlotOptimization = false;
async function onPlotGenerationAfterCommands(type, params, dryRun) {
- // 【V15.2 新增】在发送消息后,清除所有表格的“已更新”高亮状态
clearUpdatedTables();
- // 【V15.3 修正】提交删除的逻辑已移至 injector.js,此处不再需要
console.log("[Amily2-剧情优化] Generation after commands triggered", { type, params, dryRun, isProcessing: isProcessingPlotOptimization });
@@ -493,14 +641,38 @@ jQuery(async () => {
eventSource.on(event_types.MESSAGE_RECEIVED, onMessageReceived);
eventSource.on(event_types.IMPERSONATE_READY, onMessageReceived);
eventSource.on(event_types.MESSAGE_RECEIVED, (chat_id) => handleTableUpdate(chat_id));
- eventSource.on(event_types.MESSAGE_SWIPED, (chat_id) => {
+ eventSource.on(event_types.MESSAGE_SWIPED, async (chat_id) => {
const context = getContext();
if (context.chat.length < 2) {
- log(`【监察系统】检测到消息滑动,但聊天记录不足2条,已跳过状态回退。`, 'info');
+ log('【监察系统】检测到消息滑动,但聊天记录不足,已跳过状态回退。', 'info');
return;
}
- log(`【监察系统】检测到消息滑动 (SWIPED),开始执行状态回退...`, 'warn');
+
+ log('【监察系统】检测到消息滑动 (SWIPED),开始执行状态回退...', 'warn');
rollbackState();
+
+ const latestMessage = context.chat[chat_id] || context.chat[context.chat.length - 1];
+ if (latestMessage.is_user) {
+ log('【监察系统】滑动后最新消息是用户,跳过填表。', 'info');
+ renderTables();
+ return;
+ }
+
+ const settings = extension_settings[extensionName];
+ const fillingMode = settings.filling_mode || 'main-api';
+
+ if (fillingMode === 'main-api') {
+ log(`【监察系统】主填表模式,回退后强制刷新消息ID: ${chat_id}。`, 'info');
+ await handleTableUpdate(chat_id, true);
+ } else if (fillingMode === 'secondary-api' || fillingMode === 'optimized') {
+ log('【监察系统】分步/优化模式,回退后强制二次填表最新消息。', 'info');
+ await fillWithSecondaryApi(latestMessage, true);
+ } else {
+ log('【监察系统】未配置填表模式,跳过填表。', 'info');
+ }
+
+ renderTables();
+ log('【监察系统】滑动后填表完成,UI 已刷新。', 'success');
});
eventSource.on(event_types.MESSAGE_EDITED, (mes_id) => {
handleTableUpdate(mes_id);
@@ -515,7 +687,7 @@ jQuery(async () => {
setTimeout(() => {
log("【监察系统】检测到“朝代更迭”(CHAT_CHANGED),开始重修史书并刷新宫殿...", 'info');
clearHighlights();
- clearUpdatedTables(); // 【V15.2 新增】切换聊天时清除“已更新”高亮
+ clearUpdatedTables();
loadTables();
renderTables();
@@ -555,7 +727,6 @@ jQuery(async () => {
console.log('[Amily2-核心引擎] 开始执行统一注入 (聊天长度:', args[0]?.length || 0, ')');
try {
- // 【V15.3 修正】由于 injectTableData 现在是异步的,需要 await
await injectTableData(...args);
} catch (error) {
console.error('[Amily2-内存储司] 表格注入失败:', error);
@@ -593,6 +764,8 @@ jQuery(async () => {
handleUpdateCheck();
handleMessageBoard();
+ initializeRenderer();
+
if (extension_settings[extensionName].render_on_every_message) {
startContinuousRendering();
}
@@ -627,5 +800,4 @@ jQuery(async () => {
}
}
}, checkInterval);
-
});
diff --git a/manifest.json b/manifest.json
index e6d5b62..967a268 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,7 +1,7 @@
{
"name": "Amily2号聊天优化助手",
"display_name": "Amily2号助手",
- "version": "1.5.9",
+ "version": "1.6.2",
"author": "Wx-2025",
"description": "一个拥有独立UI的智能引擎,正文优化、自动总结、记忆表格、rag向量、隐藏楼层、剧情推进六大功能整合。",
"minSillyTavernVersion": "1.10.0",
@@ -28,6 +28,9 @@
+
+
+
diff --git a/ui/bindings.js b/ui/bindings.js
index fb79a18..52ede92 100644
--- a/ui/bindings.js
+++ b/ui/bindings.js
@@ -2,7 +2,7 @@ import { extension_settings, getContext } from "/scripts/extensions.js";
import { characters, this_chid, getRequestHeaders, saveSettingsDebounced, eventSource, event_types } from "/script.js";
import { defaultSettings, extensionName, saveSettings } from "../utils/settings.js";
import { pluginAuthStatus, activatePluginAuthorization, getPasswordForDate } from "../utils/auth.js";
-import { fetchModels } from "../core/api.js";
+import { fetchModels, testApiConnection } from "../core/api.js";
import { getJqyhApiSettings, testJqyhApiConnection, fetchJqyhModels } from '../core/api/JqyhApi.js';
import { safeLorebooks, safeCharLorebooks, safeLorebookEntries, isTavernHelperAvailable } from "../core/tavernhelper-compatibility.js";
@@ -421,11 +421,49 @@ function bindAmily2ModalWorldBookSettings() {
}
export function bindModalEvents() {
+ const refreshButton = document.getElementById('amily2_refresh_models');
+ if (refreshButton && !document.getElementById('amily2_test_api_connection')) {
+ const testButton = document.createElement('button');
+ testButton.id = 'amily2_test_api_connection';
+ testButton.className = 'menu_button interactable';
+ testButton.innerHTML = ' 测试连接';
+ refreshButton.insertAdjacentElement('afterend', testButton);
+ }
initializePlotOptimizationBindings();
bindAmily2ModalWorldBookSettings();
const container = $("#amily2_drawer_content").length ? $("#amily2_drawer_content") : $("#amily2_chat_optimiser");
+
+ // Collapsible sections logic
+ container.find('.collapsible-legend').each(function() {
+ $(this).on('click', function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+
+ const legend = $(this);
+ const content = legend.siblings('.collapsible-content');
+ const icon = legend.find('.collapse-icon');
+
+ const isCurrentlyVisible = content.is(':visible');
+ const isCollapsedAfterClick = isCurrentlyVisible;
+
+ if (isCollapsedAfterClick) {
+ content.hide();
+ icon.removeClass('fa-chevron-up').addClass('fa-chevron-down');
+ } else {
+ content.show();
+ icon.removeClass('fa-chevron-down').addClass('fa-chevron-up');
+ }
+
+ const sectionId = legend.text().trim();
+ if (!extension_settings[extensionName]) {
+ extension_settings[extensionName] = {};
+ }
+ extension_settings[extensionName][`collapsible_${sectionId}_collapsed`] = isCollapsedAfterClick;
+ saveSettingsDebounced();
+ });
+ });
displayDailyAuthCode();
function updateModelInputView() {
@@ -497,7 +535,7 @@ export function bindModalEvents() {
.off("click.amily2.actions")
.on(
"click.amily2.actions",
- "#amily2_refresh_models, #amily2_test, #amily2_fix_now",
+ "#amily2_refresh_models, #amily2_test_api_connection, #amily2_test, #amily2_fix_now",
async function () {
if (!pluginAuthStatus.authorized) return;
const button = $(this);
@@ -511,13 +549,16 @@ export function bindModalEvents() {
const models = await fetchModels();
if (models.length > 0) {
setAvailableModels(models);
- localStorage.setItem(
- "cached_models_amily2",
- JSON.stringify(models),
- );
+ localStorage.setItem(
+ "cached_models_amily2",
+ JSON.stringify(models),
+ );
populateModelDropdown();
}
break;
+ case "amily2_test_api_connection":
+ await testApiConnection();
+ break;
case "amily2_test":
await testReplyChecker();
break;
@@ -662,7 +703,7 @@ export function bindModalEvents() {
container
.off("click.amily2.chamber_nav")
.on("click.amily2.chamber_nav",
- "#amily2_open_plot_optimization, #amily2_open_additional_features, #amily2_open_rag_palace, #amily2_open_memorisation_forms, #amily2_open_character_world_book, #amily2_open_world_editor, #amily2_open_glossary, #amily2_back_to_main_settings, #amily2_back_to_main_from_hanlinyuan, #amily2_back_to_main_from_forms, #amily2_back_to_main_from_optimization, #amily2_back_to_main_from_cwb, #amily2_back_to_main_from_world_editor, #amily2_back_to_main_from_glossary", function () {
+ "#amily2_open_plot_optimization, #amily2_open_additional_features, #amily2_open_rag_palace, #amily2_open_memorisation_forms, #amily2_open_character_world_book, #amily2_open_world_editor, #amily2_open_glossary, #amily2_open_renderer, #amily2_back_to_main_settings, #amily2_back_to_main_from_hanlinyuan, #amily2_back_to_main_from_forms, #amily2_back_to_main_from_optimization, #amily2_back_to_main_from_cwb, #amily2_back_to_main_from_world_editor, #amily2_back_to_main_from_glossary, #amily2_renderer_back_button", function () {
if (!pluginAuthStatus.authorized) return;
const mainPanel = container.find('.plugin-features');
@@ -673,6 +714,7 @@ container
const characterWorldBookPanel = container.find('#amily2_character_world_book_panel');
const worldEditorPanel = container.find('#amily2_world_editor_panel');
const glossaryPanel = container.find('#amily2_glossary_panel');
+ const rendererPanel = container.find('#amily2_renderer_panel');
mainPanel.hide();
additionalPanel.hide();
@@ -682,8 +724,12 @@ container
characterWorldBookPanel.hide();
worldEditorPanel.hide();
glossaryPanel.hide();
+ rendererPanel.hide();
switch (this.id) {
+ case 'amily2_open_renderer':
+ rendererPanel.show();
+ break;
case 'amily2_open_plot_optimization':
plotOptimizationPanel.show();
break;
@@ -712,6 +758,7 @@ container
case 'amily2_back_to_main_from_cwb':
case 'amily2_back_to_main_from_world_editor':
case 'amily2_back_to_main_from_glossary':
+ case 'amily2_renderer_back_button':
mainPanel.show();
break;
}
diff --git a/ui/drawer.js b/ui/drawer.js
index 0062795..163d344 100644
--- a/ui/drawer.js
+++ b/ui/drawer.js
@@ -19,6 +19,7 @@ import { bindHistoriographyEvents } from "./historiography-bindings.js";
import { bindHanlinyuanEvents } from "./hanlinyuan-bindings.js";
import { bindTableEvents } from './table-bindings.js';
import { showContentModal } from "./page-window.js";
+import { initializeRendererBindings } from "../core/tavern-helper/renderer-bindings.js";
const extensionFolderPath = `scripts/extensions/third-party/${extensionName}`;
@@ -101,6 +102,10 @@ async function initializePanel(contentPanel, errorContainer) {
const glossaryPanelHtml = `${glossaryContent}
`;
mainContainer.append(glossaryPanelHtml);
+ const rendererContent = await $.get(`${extensionFolderPath}/core/tavern-helper/renderer.html`);
+ const rendererPanelHtml = `${rendererContent}
`;
+ mainContainer.append(rendererPanelHtml);
+
// 在面板创建后,加载世界书编辑器脚本
const worldEditorScriptId = 'world-editor-script';
if (!document.getElementById(worldEditorScriptId)) {
@@ -117,6 +122,7 @@ async function initializePanel(contentPanel, errorContainer) {
await loadSettings();
bindHanlinyuanEvents();
bindTableEvents();
+ initializeRendererBindings();
contentPanel.data("initialized", true);
console.log("[Amily-重构] 宫殿模块已按蓝图竣工。");
applyUpdateIndicator();
diff --git a/ui/hanlinyuan-bindings.js b/ui/hanlinyuan-bindings.js
index 71ea82a..1aab4d1 100644
--- a/ui/hanlinyuan-bindings.js
+++ b/ui/hanlinyuan-bindings.js
@@ -1 +1 @@
-const _0x13c5aa=_0x46ab;function _0x26e1(){const _0x2938be=['》的批量编纂任务已完成。成功:\x20','hly-include-user','style','\x20个Rerank模型。','宝库已清空。','apiKey','hly-manual-text','querySelectorAll','\x20个局部知识库吗?此操作无法恢复!','totalVectors','通行令牌\x20(API\x20Key):','移动知识库\x20','删除失败:\x20','预览内容已更新,可随时开始凝识。','chunkSize','sources','{{chat_text}}','signal','】移动到【','\x20个知识块','hly-locked-status','saveHLYSettings','target','\x20个局部知识库均已成功删除。','removeEventListener','24392079XYxPbE','.hly-hist-entry-checkbox','任务完成!成功录入\x20','\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20','tags','[翰林院-枢纽]\x20编纂过程发生严重错误:','\x20失败:\x20','翰林院启奏','localToGlobal','【手动存档】所有设定已存档封印。','圣旨已下','checkbox','您确定要永久删除【当前角色】的全部\x20','hly-unified-injection-depth','clearJob','>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20 \x0a\x20\x20\x20\x20\x20\x20\x20\x20','已采集\x20','novel','rerank','getVectorCount','checked','[翰林院-枢纽]\x20加载书库列表失败:','3174224fiPGcE','fa-exclamation-triangle','400393eayTjI',')\x20已被删除','getChatId','processed','hly-kb-delete-btn','hly-rerank-model','\x20条消息,开始凝识...','会话已解锁,将跟随当前角色。','previousElementSibling','message','翰林院使用教程','未检测到预览文本,按标准流程采集消息...','hly-retrieval-enabled','val','\x20楼:\x20[','local_proxy','\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20