mirror of
https://github.com/Wx-2025/ST-Amily2-Chat-Optimisation.git
synced 2026-06-06 09:15:50 +00:00
ci: auto build & obfuscate [2026-04-08 17:38:16] (Jenkins #11)
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { extension_settings } from '/scripts/extensions.js';
|
import { extension_settings } from '/scripts/extensions.js';
|
||||||
import { extensionName } from '../../utils/settings.js';
|
import { extensionName } from '../../utils/settings.js';
|
||||||
import { saveSettingsDebounced } from '/script.js';
|
import { saveSettingsDebounced } from '/script.js';
|
||||||
|
import { configManager } from '../../utils/config/ConfigManager.js';
|
||||||
import { world_names } from '/scripts/world-info.js';
|
import { world_names } from '/scripts/world-info.js';
|
||||||
import { state } from './cwb_state.js';
|
import { state } from './cwb_state.js';
|
||||||
import { cwbCompleteDefaultSettings } from './cwb_config.js';
|
import { cwbCompleteDefaultSettings } from './cwb_config.js';
|
||||||
@@ -38,7 +39,7 @@ function saveApiConfig() {
|
|||||||
const settings = getSettings();
|
const settings = getSettings();
|
||||||
settings.cwb_api_mode = $panel.find('#cwb-api-mode').val();
|
settings.cwb_api_mode = $panel.find('#cwb-api-mode').val();
|
||||||
settings.cwb_api_url = $panel.find('#cwb-api-url').val().trim();
|
settings.cwb_api_url = $panel.find('#cwb-api-url').val().trim();
|
||||||
settings.cwb_api_key = $panel.find('#cwb-api-key').val();
|
configManager.set('cwb_api_key', $panel.find('#cwb-api-key').val());
|
||||||
settings.cwb_api_model = $panel.find('#cwb-api-model').val();
|
settings.cwb_api_model = $panel.find('#cwb-api-model').val();
|
||||||
settings.cwb_tavern_profile = $panel.find('#cwb-tavern-profile').val();
|
settings.cwb_tavern_profile = $panel.find('#cwb-tavern-profile').val();
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ function saveApiConfig() {
|
|||||||
function clearApiConfig() {
|
function clearApiConfig() {
|
||||||
const settings = getSettings();
|
const settings = getSettings();
|
||||||
settings.cwb_api_url = '';
|
settings.cwb_api_url = '';
|
||||||
settings.cwb_api_key = '';
|
configManager.set('cwb_api_key', '');
|
||||||
settings.cwb_api_model = '';
|
settings.cwb_api_model = '';
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
state.customApiConfig.url = '';
|
state.customApiConfig.url = '';
|
||||||
@@ -283,13 +284,11 @@ export function bindSettingsEvents($settingsPanel) {
|
|||||||
$panel.on('input', '#cwb-api-key', function() {
|
$panel.on('input', '#cwb-api-key', function() {
|
||||||
const apiKey = $(this).val();
|
const apiKey = $(this).val();
|
||||||
|
|
||||||
// 同时更新设置和状态
|
// 同时更新设置和状态(API Key 经 configManager 写入 localStorage)
|
||||||
getSettings().cwb_api_key = apiKey;
|
configManager.set('cwb_api_key', apiKey);
|
||||||
state.customApiConfig.apiKey = apiKey;
|
state.customApiConfig.apiKey = apiKey;
|
||||||
|
|
||||||
saveSettingsDebounced();
|
console.log('[CWB] API Key已更新 - 状态长度:', state.customApiConfig.apiKey?.length || 0);
|
||||||
|
|
||||||
console.log('[CWB] API Key已更新 - 设置长度:', getSettings().cwb_api_key?.length || 0, ', 状态长度:', state.customApiConfig.apiKey?.length || 0);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$panel.on('change', '#cwb-api-model', function() {
|
$panel.on('change', '#cwb-api-model', function() {
|
||||||
@@ -489,7 +488,7 @@ function updateUiWithSettings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$panel.find('#cwb-api-url').val(settings.cwb_api_url);
|
$panel.find('#cwb-api-url').val(settings.cwb_api_url);
|
||||||
$panel.find('#cwb-api-key').val(settings.cwb_api_key);
|
$panel.find('#cwb-api-key').val(configManager.get('cwb_api_key') || '');
|
||||||
$panel.find('#cwb-tavern-profile').val(settings.cwb_tavern_profile);
|
$panel.find('#cwb-tavern-profile').val(settings.cwb_tavern_profile);
|
||||||
|
|
||||||
const $modelSelect = $panel.find('#cwb-api-model');
|
const $modelSelect = $panel.find('#cwb-api-model');
|
||||||
@@ -574,7 +573,7 @@ export function loadSettings() {
|
|||||||
state.isIncrementalUpdateEnabled = finalSettings.cwb_incremental_update_enabled;
|
state.isIncrementalUpdateEnabled = finalSettings.cwb_incremental_update_enabled;
|
||||||
|
|
||||||
state.customApiConfig.url = finalSettings.cwb_api_url || '';
|
state.customApiConfig.url = finalSettings.cwb_api_url || '';
|
||||||
state.customApiConfig.apiKey = finalSettings.cwb_api_key || '';
|
state.customApiConfig.apiKey = configManager.get('cwb_api_key') || '';
|
||||||
state.customApiConfig.model = finalSettings.cwb_api_model || '';
|
state.customApiConfig.model = finalSettings.cwb_api_model || '';
|
||||||
|
|
||||||
state.currentBreakArmorPrompt = finalSettings.cwb_break_armor_prompt;
|
state.currentBreakArmorPrompt = finalSettings.cwb_break_armor_prompt;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
import { extension_settings } from '/scripts/extensions.js';
|
import { extension_settings } from '/scripts/extensions.js';
|
||||||
import { saveSettingsDebounced } from '/script.js';
|
import { saveSettingsDebounced } from '/script.js';
|
||||||
import { amilyHelper } from '../../core/tavern-helper/main.js';
|
import { amilyHelper } from '../../core/tavern-helper/main.js';
|
||||||
|
import { configManager } from '../../utils/config/ConfigManager.js';
|
||||||
|
|
||||||
const { jQuery: $, SillyTavern } = window;
|
const { jQuery: $, SillyTavern } = window;
|
||||||
|
|
||||||
@@ -675,8 +676,7 @@
|
|||||||
|
|
||||||
$('#cwb-api-key').off('input').on('input', function() {
|
$('#cwb-api-key').off('input').on('input', function() {
|
||||||
const value = $(this).val();
|
const value = $(this).val();
|
||||||
extension_settings[extensionName].cwb_api_key = value;
|
configManager.set('cwb_api_key', value);
|
||||||
saveSettingsDebounced();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#cwb-model').off('input').on('input', function() {
|
$('#cwb-model').off('input').on('input', function() {
|
||||||
|
|||||||
@@ -159,6 +159,13 @@
|
|||||||
<label for="amily2_pf_temperature">温度(Temperature)</label>
|
<label for="amily2_pf_temperature">温度(Temperature)</label>
|
||||||
<input id="amily2_pf_temperature" type="number" class="text_pole" min="0" max="2" step="0.1" value="1.0" />
|
<input id="amily2_pf_temperature" type="number" class="text_pole" min="0" max="2" step="0.1" value="1.0" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="amily2_settings_block" style="flex-direction:row; align-items:center; gap:8px;">
|
||||||
|
<input id="amily2_pf_fake_stream" type="checkbox" />
|
||||||
|
<label for="amily2_pf_fake_stream">
|
||||||
|
启用假流式(防 CF 超时)
|
||||||
|
<small class="notes" style="display:block; font-weight:normal;">以 stream:true 接收 SSE 后拼接,适用于经 CloudFlare 免费代理的接口</small>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
35
core/api.js
35
core/api.js
@@ -1,6 +1,7 @@
|
|||||||
import { extension_settings, getContext } from "/scripts/extensions.js";
|
import { extension_settings, getContext } from "/scripts/extensions.js";
|
||||||
import { characters } from "/script.js";
|
import { characters } from "/script.js";
|
||||||
import { getSlotProfile } from './api/api-resolver.js';
|
import { getSlotProfile } from './api/api-resolver.js';
|
||||||
|
import { configManager } from '../utils/config/ConfigManager.js';
|
||||||
import { world_names } from "/scripts/world-info.js";
|
import { world_names } from "/scripts/world-info.js";
|
||||||
import { extensionName } from "../utils/settings.js";
|
import { extensionName } from "../utils/settings.js";
|
||||||
import { extractContentByTag, replaceContentByTag, extractFullTagBlock } from '../utils/tagProcessor.js';
|
import { extractContentByTag, replaceContentByTag, extractFullTagBlock } from '../utils/tagProcessor.js';
|
||||||
@@ -449,12 +450,44 @@ export async function getApiSettings(slot = 'main') {
|
|||||||
// 温度 / MaxTokens 读面板值(profile-sync 保留了这些输入框)
|
// 温度 / MaxTokens 读面板值(profile-sync 保留了这些输入框)
|
||||||
maxTokens: s.maxTokens ?? profile.maxTokens ?? 65500,
|
maxTokens: s.maxTokens ?? profile.maxTokens ?? 65500,
|
||||||
temperature: s.temperature ?? profile.temperature ?? 1.0,
|
temperature: s.temperature ?? profile.temperature ?? 1.0,
|
||||||
|
fakeStream: profile.fakeStream ?? false,
|
||||||
tavernProfile: '',
|
tavernProfile: '',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 降级:读旧 DOM 面板配置
|
// 降级:按槽位读取各自的独立配置
|
||||||
const settings = extension_settings[extensionName] || {};
|
const settings = extension_settings[extensionName] || {};
|
||||||
|
|
||||||
|
// plotOpt 槽有独立 API 面板(剧情优化),优先读其专属设置
|
||||||
|
if (slot === 'plotOpt') {
|
||||||
|
const apiMode = settings.plotOpt_apiMode || 'openai_test';
|
||||||
|
if (apiMode === 'sillytavern_preset') {
|
||||||
|
const context = getContext();
|
||||||
|
const profileId = settings.plotOpt_tavernProfile || '';
|
||||||
|
const stProfile = context.extensionSettings?.connectionManager?.profiles?.find(p => p.id === profileId);
|
||||||
|
return {
|
||||||
|
apiProvider: 'sillytavern_preset',
|
||||||
|
apiUrl: '',
|
||||||
|
apiKey: '',
|
||||||
|
model: stProfile?.openai_model || 'Preset Model',
|
||||||
|
maxTokens: settings.plotOpt_max_tokens ?? 65500,
|
||||||
|
temperature: settings.plotOpt_temperature ?? 1.0,
|
||||||
|
tavernProfile: profileId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
apiProvider: apiMode,
|
||||||
|
apiUrl: settings.plotOpt_apiUrl?.trim() || '',
|
||||||
|
apiKey: configManager.get('plotOpt_apiKey') || '',
|
||||||
|
model: document.getElementById('amily2_opt_model')?.value?.trim()
|
||||||
|
|| settings.plotOpt_model || '',
|
||||||
|
maxTokens: settings.plotOpt_max_tokens ?? 65500,
|
||||||
|
temperature: settings.plotOpt_temperature ?? 1.0,
|
||||||
|
tavernProfile: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// main 槽(及其余未明确处理的槽):读主面板 DOM 配置
|
||||||
const apiProvider = document.getElementById('amily2_api_provider')?.value || 'openai';
|
const apiProvider = document.getElementById('amily2_api_provider')?.value || 'openai';
|
||||||
|
|
||||||
let model;
|
let model;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { renderTables } from '../../ui/table-bindings.js';
|
|||||||
import { extensionName } from "../../utils/settings.js";
|
import { extensionName } from "../../utils/settings.js";
|
||||||
import { convertTablesToCsvString, convertSelectedTablesToCsvString, saveStateToMessage, getMemoryState, updateTableFromText, getBatchFillerRuleTemplate, getBatchFillerFlowTemplate } from './manager.js';
|
import { convertTablesToCsvString, convertSelectedTablesToCsvString, saveStateToMessage, getMemoryState, updateTableFromText, getBatchFillerRuleTemplate, getBatchFillerFlowTemplate } from './manager.js';
|
||||||
import { getPresetPrompts, getMixedOrder } from '../../PresetSettings/index.js';
|
import { getPresetPrompts, getMixedOrder } from '../../PresetSettings/index.js';
|
||||||
import { callAI, generateRandomSeed, getApiSettings } from '../api.js';
|
import { callAI, generateRandomSeed } from '../api.js';
|
||||||
import { callNccsAI } from '../api/NccsApi.js';
|
import { callNccsAI } from '../api/NccsApi.js';
|
||||||
|
|
||||||
export async function reorganizeTableContent(selectedTableIndices) {
|
export async function reorganizeTableContent(selectedTableIndices) {
|
||||||
@@ -20,13 +20,6 @@ export async function reorganizeTableContent(selectedTableIndices) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolvedApi = await getApiSettings('main');
|
|
||||||
const { apiUrl, apiKey, model, temperature, maxTokens, forceProxyForCustomApi } = resolvedApi ?? settings;
|
|
||||||
if (!apiUrl || !model) {
|
|
||||||
toastr.error("主API的URL或模型未配置,重新整理功能无法启动。", "Amily2-重新整理");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
toastr.info('正在重新整理表格内容...', 'Amily2-重新整理');
|
toastr.info('正在重新整理表格内容...', 'Amily2-重新整理');
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { updateOrInsertTableInChat } from '../../ui/message-table-renderer.js';
|
|||||||
import { extensionName } from "../../utils/settings.js";
|
import { extensionName } from "../../utils/settings.js";
|
||||||
import { updateTableFromText, getBatchFillerRuleTemplate, getBatchFillerFlowTemplate, convertTablesToCsvString, saveStateToMessage, getMemoryState, clearHighlights } from './manager.js';
|
import { updateTableFromText, getBatchFillerRuleTemplate, getBatchFillerFlowTemplate, convertTablesToCsvString, saveStateToMessage, getMemoryState, clearHighlights } from './manager.js';
|
||||||
import { getPresetPrompts, getMixedOrder } from '../../PresetSettings/index.js';
|
import { getPresetPrompts, getMixedOrder } from '../../PresetSettings/index.js';
|
||||||
import { callAI, generateRandomSeed, getApiSettings } from '../api.js';
|
import { callAI, generateRandomSeed } from '../api.js';
|
||||||
import { callNccsAI } from '../api/NccsApi.js';
|
import { callNccsAI } from '../api/NccsApi.js';
|
||||||
import { extractBlocksByTags, applyExclusionRules } from '../utils/rag-tag-extractor.js';
|
import { extractBlocksByTags, applyExclusionRules } from '../utils/rag-tag-extractor.js';
|
||||||
import { safeLorebookEntries } from '../tavernhelper-compatibility.js';
|
import { safeLorebookEntries } from '../tavernhelper-compatibility.js';
|
||||||
@@ -92,15 +92,6 @@ export async function fillWithSecondaryApi(latestMessage, forceRun = false) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolvedApi = await getApiSettings('main');
|
|
||||||
const { apiUrl, apiKey, model, temperature, maxTokens, forceProxyForCustomApi } = resolvedApi ?? settings;
|
|
||||||
if (!apiUrl || !model) {
|
|
||||||
if (!window.secondaryApiUrlWarned) {
|
|
||||||
toastr.error("主API的URL或模型未配置,分步填表功能无法启动。", "Amily2-分步填表");
|
|
||||||
window.secondaryApiUrlWarned = true;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const bufferSize = parseInt(settings.secondary_filler_buffer || 0, 10);
|
const bufferSize = parseInt(settings.secondary_filler_buffer || 0, 10);
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { extension_settings, getContext } from "/scripts/extensions.js";
|
import { extension_settings, getContext } from "/scripts/extensions.js";
|
||||||
import { saveSettingsDebounced, eventSource, event_types } from "/script.js";
|
import { saveSettingsDebounced, eventSource, event_types } from "/script.js";
|
||||||
import { extensionName } from "../utils/settings.js";
|
import { extensionName } from "../utils/settings.js";
|
||||||
|
import { configManager } from '../utils/config/ConfigManager.js';
|
||||||
|
import { SENSITIVE_KEYS } from '../utils/config/sensitive-keys.js';
|
||||||
import { safeLorebooks, safeLorebookEntries, safeUpdateLorebookEntries } from '../core/tavernhelper-compatibility.js';
|
import { safeLorebooks, safeLorebookEntries, safeUpdateLorebookEntries } from '../core/tavernhelper-compatibility.js';
|
||||||
import { testSybdApiConnection, fetchSybdModels } from '../core/api/SybdApi.js';
|
import { testSybdApiConnection, fetchSybdModels } from '../core/api/SybdApi.js';
|
||||||
import { handleFileUpload, processNovel } from './index.js';
|
import { handleFileUpload, processNovel } from './index.js';
|
||||||
@@ -29,18 +31,21 @@ function loadSettingsToUI() {
|
|||||||
const inputs = container.querySelectorAll('[data-setting-key]');
|
const inputs = container.querySelectorAll('[data-setting-key]');
|
||||||
inputs.forEach(target => {
|
inputs.forEach(target => {
|
||||||
const key = target.dataset.settingKey;
|
const key = target.dataset.settingKey;
|
||||||
const value = settings[key];
|
// 敏感字段从 configManager(localStorage)读取,其余从 extension_settings 读取
|
||||||
|
const value = SENSITIVE_KEYS.has(key) ? configManager.get(key) : settings[key];
|
||||||
|
|
||||||
if (value === undefined) {
|
if (value === undefined || value === null || value === '') {
|
||||||
let defaultValue;
|
if (!SENSITIVE_KEYS.has(key)) {
|
||||||
if (target.type === 'checkbox') {
|
let defaultValue;
|
||||||
defaultValue = target.checked;
|
if (target.type === 'checkbox') {
|
||||||
} else if (target.type === 'range') {
|
defaultValue = target.checked;
|
||||||
defaultValue = target.dataset.type === 'float' ? parseFloat(target.value) : parseInt(target.value, 10);
|
} else if (target.type === 'range') {
|
||||||
} else {
|
defaultValue = target.dataset.type === 'float' ? parseFloat(target.value) : parseInt(target.value, 10);
|
||||||
defaultValue = target.value;
|
} else {
|
||||||
|
defaultValue = target.value;
|
||||||
|
}
|
||||||
|
updateAndSaveSetting(key, defaultValue);
|
||||||
}
|
}
|
||||||
updateAndSaveSetting(key, defaultValue);
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -91,7 +96,12 @@ function bindAutoSaveEvents() {
|
|||||||
case 'boolean': value = (typeof value === 'boolean') ? value : (value === 'true'); break;
|
case 'boolean': value = (typeof value === 'boolean') ? value : (value === 'true'); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAndSaveSetting(key, value);
|
// 敏感字段(API Key)经 configManager 写入 localStorage
|
||||||
|
if (SENSITIVE_KEYS.has(key)) {
|
||||||
|
configManager.set(key, value);
|
||||||
|
} else {
|
||||||
|
updateAndSaveSetting(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
if (key === 'sybdApiMode') {
|
if (key === 'sybdApiMode') {
|
||||||
updateConfigVisibility(value);
|
updateConfigVisibility(value);
|
||||||
|
|||||||
9
index.js
9
index.js
@@ -568,11 +568,12 @@ async function onPlotGenerationAfterCommands(type, params, dryRun) {
|
|||||||
if (globalSettings?.plotOpt_enabled === false) return false;
|
if (globalSettings?.plotOpt_enabled === false) return false;
|
||||||
|
|
||||||
const isJqyhEnabled = globalSettings?.jqyhEnabled === true;
|
const isJqyhEnabled = globalSettings?.jqyhEnabled === true;
|
||||||
const hasMainProfile = !!apiProfileManager.getAssignment('main') || !!apiProfileManager.getAssignment('plotOpt');
|
const hasProfile = !!apiProfileManager.getAssignment('main') || !!apiProfileManager.getAssignment('plotOpt');
|
||||||
const isMainApiConfigured = hasMainProfile || !!globalSettings?.apiUrl || !!globalSettings?.tavernProfile;
|
const hasLegacyConfig = !!globalSettings?.apiUrl || !!globalSettings?.tavernProfile
|
||||||
|
|| !!globalSettings?.plotOpt_apiUrl || !!globalSettings?.plotOpt_tavernProfile;
|
||||||
|
|
||||||
if (!isJqyhEnabled && !isMainApiConfigured) {
|
if (!isJqyhEnabled && !hasProfile && !hasLegacyConfig) {
|
||||||
console.log("[Amily2-剧情优化] 优化已启用,但Jqyh API已禁用且主API未配置(无 Profile 分配亦无旧设置)。");
|
console.log("[Amily2-剧情优化] 优化已启用,但未配置任何可用的 API(无 Profile 分配亦无独立配置)。");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Amily2号聊天优化助手",
|
"name": "Amily2号聊天优化助手",
|
||||||
"display_name": "Amily2号助手",
|
"display_name": "Amily2号助手",
|
||||||
"version": "2.0.1",
|
"version": "2.0.2",
|
||||||
"author": "Wx-2025",
|
"author": "Wx-2025",
|
||||||
"description": "一个拥有独立UI的智能引擎,正文优化、自动总结、记忆表格、rag向量、隐藏楼层、剧情推进等多功能整合。",
|
"description": "一个拥有独立UI的智能引擎,正文优化、自动总结、记忆表格、rag向量、隐藏楼层、剧情推进等多功能整合。",
|
||||||
"minSillyTavernVersion": "1.10.0",
|
"minSillyTavernVersion": "1.10.0",
|
||||||
|
|||||||
@@ -343,6 +343,7 @@ async function openModal($c, id) {
|
|||||||
if (p.type === 'chat') {
|
if (p.type === 'chat') {
|
||||||
$c.find('#amily2_pf_max_tokens').val(p.maxTokens);
|
$c.find('#amily2_pf_max_tokens').val(p.maxTokens);
|
||||||
$c.find('#amily2_pf_temperature').val(p.temperature);
|
$c.find('#amily2_pf_temperature').val(p.temperature);
|
||||||
|
$c.find('#amily2_pf_fake_stream').prop('checked', p.fakeStream ?? false);
|
||||||
} else if (p.type === 'embedding') {
|
} else if (p.type === 'embedding') {
|
||||||
$c.find('#amily2_pf_dimensions').val(p.dimensions ?? '');
|
$c.find('#amily2_pf_dimensions').val(p.dimensions ?? '');
|
||||||
$c.find('#amily2_pf_encoding_format').val(p.encodingFormat);
|
$c.find('#amily2_pf_encoding_format').val(p.encodingFormat);
|
||||||
@@ -362,6 +363,7 @@ async function openModal($c, id) {
|
|||||||
_handleProviderChange($c, 'openai');
|
_handleProviderChange($c, 'openai');
|
||||||
$c.find('#amily2_pf_max_tokens').val(65500);
|
$c.find('#amily2_pf_max_tokens').val(65500);
|
||||||
$c.find('#amily2_pf_temperature').val(1.0);
|
$c.find('#amily2_pf_temperature').val(1.0);
|
||||||
|
$c.find('#amily2_pf_fake_stream').prop('checked', false);
|
||||||
$c.find('#amily2_pf_dimensions').val('');
|
$c.find('#amily2_pf_dimensions').val('');
|
||||||
$c.find('#amily2_pf_encoding_format').val('float');
|
$c.find('#amily2_pf_encoding_format').val('float');
|
||||||
$c.find('#amily2_pf_top_n').val(5);
|
$c.find('#amily2_pf_top_n').val(5);
|
||||||
@@ -401,6 +403,7 @@ async function saveProfile($c) {
|
|||||||
if (type === 'chat') {
|
if (type === 'chat') {
|
||||||
data.maxTokens = parseInt($c.find('#amily2_pf_max_tokens').val(), 10) || 65500;
|
data.maxTokens = parseInt($c.find('#amily2_pf_max_tokens').val(), 10) || 65500;
|
||||||
data.temperature = parseFloat($c.find('#amily2_pf_temperature').val()) || 1.0;
|
data.temperature = parseFloat($c.find('#amily2_pf_temperature').val()) || 1.0;
|
||||||
|
data.fakeStream = $c.find('#amily2_pf_fake_stream').prop('checked');
|
||||||
} else if (type === 'embedding') {
|
} else if (type === 'embedding') {
|
||||||
const dim = $c.find('#amily2_pf_dimensions').val();
|
const dim = $c.find('#amily2_pf_dimensions').val();
|
||||||
data.dimensions = dim ? parseInt(dim, 10) : null;
|
data.dimensions = dim ? parseInt(dim, 10) : null;
|
||||||
@@ -582,8 +585,39 @@ async function _testConnection($c) {
|
|||||||
|
|
||||||
if (modelsResp.ok) {
|
if (modelsResp.ok) {
|
||||||
const rawData = await modelsResp.json();
|
const rawData = await modelsResp.json();
|
||||||
const list = Array.isArray(rawData) ? rawData : (rawData.data ?? rawData.models ?? []);
|
const rawList = Array.isArray(rawData) ? rawData : (rawData.data ?? rawData.models ?? []);
|
||||||
|
const list = Array.isArray(rawList) ? rawList : [];
|
||||||
const count = list.length;
|
const count = list.length;
|
||||||
|
|
||||||
|
// chat 类型额外发一次假补全,验证 completion 端点也能正常鉴权
|
||||||
|
const type = $c.find('#amily2_pf_type').val();
|
||||||
|
const $sel = $c.find('#amily2_pf_model_select');
|
||||||
|
const model = ($sel.is(':visible') ? $sel.val() : $c.find('#amily2_pf_model').val()).trim();
|
||||||
|
|
||||||
|
if (type === 'chat' && model) {
|
||||||
|
$result.text('模型列表 ✓,正在验证补全端点…').css('color', 'var(--SmartThemeQuoteColor)');
|
||||||
|
const genResp = await fetch('/api/backends/chat-completions/generate', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { ...getRequestHeaders(), 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
reverse_proxy: apiUrl,
|
||||||
|
proxy_password: apiKey,
|
||||||
|
chat_completion_source: 'openai',
|
||||||
|
model,
|
||||||
|
messages: [{ role: 'user', content: 'Hi' }],
|
||||||
|
max_tokens: 1,
|
||||||
|
stream: false,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
if (!genResp.ok) {
|
||||||
|
const genErr = await genResp.json().catch(() => ({}));
|
||||||
|
const genMsg = genErr?.error?.message || `补全端点返回 HTTP ${genResp.status}`;
|
||||||
|
$result.text(`模型列表 ✓,补全失败:${genMsg}`).css('color', 'var(--warning-color)');
|
||||||
|
toastr.warning(`补全端点测试失败:${genMsg}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$result.text(`连接成功${count ? `,${count} 个可用模型` : ''}`).css('color', 'var(--green)');
|
$result.text(`连接成功${count ? `,${count} 个可用模型` : ''}`).css('color', 'var(--green)');
|
||||||
toastr.success('连接测试通过!');
|
toastr.success('连接测试通过!');
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { defaultSettings, extensionName, saveSettings, extensionBasePath } from
|
|||||||
import { pluginAuthStatus, activatePluginAuthorization, getPasswordForDate } from "../utils/auth.js";
|
import { pluginAuthStatus, activatePluginAuthorization, getPasswordForDate } from "../utils/auth.js";
|
||||||
import { fetchModels, testApiConnection } from "../core/api.js";
|
import { fetchModels, testApiConnection } from "../core/api.js";
|
||||||
import { safeLorebooks, safeCharLorebooks, safeLorebookEntries } from "../core/tavernhelper-compatibility.js";
|
import { safeLorebooks, safeCharLorebooks, safeLorebookEntries } from "../core/tavernhelper-compatibility.js";
|
||||||
|
import { configManager } from '../utils/config/ConfigManager.js';
|
||||||
|
|
||||||
import { setAvailableModels, populateModelDropdown, getLatestUpdateInfo } from "./state.js";
|
import { setAvailableModels, populateModelDropdown, getLatestUpdateInfo } from "./state.js";
|
||||||
import { fixCommand, testReplyChecker } from "../core/commands.js";
|
import { fixCommand, testReplyChecker } from "../core/commands.js";
|
||||||
@@ -1038,7 +1039,12 @@ export function bindModalEvents() {
|
|||||||
.on("change.amily2.text", "#amily2_api_url, #amily2_api_key, #amily2_optimization_target_tag", function () {
|
.on("change.amily2.text", "#amily2_api_url, #amily2_api_key, #amily2_optimization_target_tag", function () {
|
||||||
if (!pluginAuthStatus.authorized) return;
|
if (!pluginAuthStatus.authorized) return;
|
||||||
const key = snakeToCamel(this.id.replace("amily2_", ""));
|
const key = snakeToCamel(this.id.replace("amily2_", ""));
|
||||||
updateAndSaveSetting(key, this.value);
|
// apiKey 是敏感字段,必须经 configManager 写入 localStorage
|
||||||
|
if (key === 'apiKey') {
|
||||||
|
configManager.set(key, this.value);
|
||||||
|
} else {
|
||||||
|
updateAndSaveSetting(key, this.value);
|
||||||
|
}
|
||||||
toastr.success(`配置 [${key}] 已自动保存!`, "Amily2号");
|
toastr.success(`配置 [${key}] 已自动保存!`, "Amily2号");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
} from "../utils/settings.js";
|
} from "../utils/settings.js";
|
||||||
import { showHtmlModal } from './page-window.js';
|
import { showHtmlModal } from './page-window.js';
|
||||||
import { applyExclusionRules, extractBlocksByTags } from '../core/utils/rag-tag-extractor.js';
|
import { applyExclusionRules, extractBlocksByTags } from '../core/utils/rag-tag-extractor.js';
|
||||||
|
import { configManager } from '../utils/config/ConfigManager.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getAvailableWorldbooks, getLoresForWorldbook,
|
getAvailableWorldbooks, getLoresForWorldbook,
|
||||||
@@ -459,16 +460,23 @@ function bindNgmsApiEvents() {
|
|||||||
// API配置字段绑定
|
// API配置字段绑定
|
||||||
const apiFields = [
|
const apiFields = [
|
||||||
{ id: 'amily2_ngms_api_url', key: 'ngmsApiUrl' },
|
{ id: 'amily2_ngms_api_url', key: 'ngmsApiUrl' },
|
||||||
{ id: 'amily2_ngms_api_key', key: 'ngmsApiKey' },
|
{ id: 'amily2_ngms_api_key', key: 'ngmsApiKey', sensitive: true },
|
||||||
{ id: 'amily2_ngms_model', key: 'ngmsModel' }
|
{ id: 'amily2_ngms_model', key: 'ngmsModel' }
|
||||||
];
|
];
|
||||||
|
|
||||||
apiFields.forEach(field => {
|
apiFields.forEach(field => {
|
||||||
const element = document.getElementById(field.id);
|
const element = document.getElementById(field.id);
|
||||||
if (element) {
|
if (element) {
|
||||||
element.value = extension_settings[extensionName][field.key] || '';
|
// 敏感字段(API Key)从 configManager(localStorage)读取
|
||||||
|
element.value = field.sensitive
|
||||||
|
? (configManager.get(field.key) || '')
|
||||||
|
: (extension_settings[extensionName][field.key] || '');
|
||||||
element.addEventListener('change', function() {
|
element.addEventListener('change', function() {
|
||||||
updateAndSaveSetting(field.key, this.value);
|
if (field.sensitive) {
|
||||||
|
configManager.set(field.key, this.value);
|
||||||
|
} else {
|
||||||
|
updateAndSaveSetting(field.key, this.value);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { testConcurrentApiConnection, fetchConcurrentModels } from '../core/api/
|
|||||||
import { safeLorebooks, safeCharLorebooks, safeLorebookEntries } from "../core/tavernhelper-compatibility.js";
|
import { safeLorebooks, safeCharLorebooks, safeLorebookEntries } from "../core/tavernhelper-compatibility.js";
|
||||||
import { createDrawer } from '../ui/drawer.js';
|
import { createDrawer } from '../ui/drawer.js';
|
||||||
import { pluginAuthStatus } from "../utils/auth.js";
|
import { pluginAuthStatus } from "../utils/auth.js";
|
||||||
|
import { configManager } from '../utils/config/ConfigManager.js';
|
||||||
|
import { SENSITIVE_KEYS } from '../utils/config/sensitive-keys.js';
|
||||||
|
|
||||||
// ========== Prompt Cache (module-level state) ==========
|
// ========== Prompt Cache (module-level state) ==========
|
||||||
|
|
||||||
@@ -161,6 +163,9 @@ async function opt_saveSetting(key, value) {
|
|||||||
console.error(`[${extensionName}] 保存角色数据失败:`, error);
|
console.error(`[${extensionName}] 保存角色数据失败:`, error);
|
||||||
toastr.error('无法保存角色卡设置,请检查控制台。');
|
toastr.error('无法保存角色卡设置,请检查控制台。');
|
||||||
}
|
}
|
||||||
|
} else if (SENSITIVE_KEYS.has(key)) {
|
||||||
|
// 敏感字段(API Key)经 configManager 写入 localStorage
|
||||||
|
configManager.set(key, value);
|
||||||
} else {
|
} else {
|
||||||
if (!extension_settings[extensionName]) {
|
if (!extension_settings[extensionName]) {
|
||||||
extension_settings[extensionName] = {};
|
extension_settings[extensionName] = {};
|
||||||
@@ -622,7 +627,8 @@ function opt_loadSettings(panel) {
|
|||||||
panel.find('#amily2_opt_worldbook_enabled').prop('checked', settings.plotOpt_worldbookEnabled);
|
panel.find('#amily2_opt_worldbook_enabled').prop('checked', settings.plotOpt_worldbookEnabled);
|
||||||
panel.find('#amily2_opt_new_memory_logic_enabled').prop('checked', settings.plotOpt_newMemoryLogicEnabled);
|
panel.find('#amily2_opt_new_memory_logic_enabled').prop('checked', settings.plotOpt_newMemoryLogicEnabled);
|
||||||
panel.find('#amily2_opt_api_url').val(settings.plotOpt_apiUrl);
|
panel.find('#amily2_opt_api_url').val(settings.plotOpt_apiUrl);
|
||||||
panel.find('#amily2_opt_api_key').val(settings.plotOpt_apiKey);
|
// plotOpt_apiKey 是敏感字段,从 configManager(localStorage)读取
|
||||||
|
panel.find('#amily2_opt_api_key').val(configManager.get('plotOpt_apiKey') || '');
|
||||||
|
|
||||||
const modelInput = panel.find('#amily2_opt_model');
|
const modelInput = panel.find('#amily2_opt_model');
|
||||||
const modelSelect = panel.find('#amily2_opt_model_select');
|
const modelSelect = panel.find('#amily2_opt_model_select');
|
||||||
@@ -701,14 +707,17 @@ function bindConcurrentApiEvents() {
|
|||||||
const fields = [
|
const fields = [
|
||||||
{ id: 'amily2_plotOpt_concurrentApiProvider', key: 'plotOpt_concurrentApiProvider' },
|
{ id: 'amily2_plotOpt_concurrentApiProvider', key: 'plotOpt_concurrentApiProvider' },
|
||||||
{ id: 'amily2_plotOpt_concurrentApiUrl', key: 'plotOpt_concurrentApiUrl' },
|
{ id: 'amily2_plotOpt_concurrentApiUrl', key: 'plotOpt_concurrentApiUrl' },
|
||||||
{ id: 'amily2_plotOpt_concurrentApiKey', key: 'plotOpt_concurrentApiKey' },
|
{ id: 'amily2_plotOpt_concurrentApiKey', key: 'plotOpt_concurrentApiKey', sensitive: true },
|
||||||
{ id: 'amily2_plotOpt_concurrentModel', key: 'plotOpt_concurrentModel' }
|
{ id: 'amily2_plotOpt_concurrentModel', key: 'plotOpt_concurrentModel' }
|
||||||
];
|
];
|
||||||
|
|
||||||
fields.forEach(field => {
|
fields.forEach(field => {
|
||||||
const element = document.getElementById(field.id);
|
const element = document.getElementById(field.id);
|
||||||
if (element) {
|
if (element) {
|
||||||
element.value = settings[field.key] || '';
|
// 敏感字段(API Key)从 configManager(localStorage)读取
|
||||||
|
element.value = field.sensitive
|
||||||
|
? (configManager.get(field.key) || '')
|
||||||
|
: (settings[field.key] || '');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -787,9 +796,13 @@ function bindConcurrentApiEvents() {
|
|||||||
const element = document.getElementById(field.id);
|
const element = document.getElementById(field.id);
|
||||||
if (element) {
|
if (element) {
|
||||||
element.addEventListener('change', function() {
|
element.addEventListener('change', function() {
|
||||||
if (!extension_settings[extensionName]) extension_settings[extensionName] = {};
|
if (field.sensitive) {
|
||||||
extension_settings[extensionName][field.key] = this.value;
|
configManager.set(field.key, this.value);
|
||||||
saveSettingsDebounced();
|
} else {
|
||||||
|
if (!extension_settings[extensionName]) extension_settings[extensionName] = {};
|
||||||
|
extension_settings[extensionName][field.key] = this.value;
|
||||||
|
saveSettingsDebounced();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1384,16 +1397,23 @@ function bindJqyhApiEvents() {
|
|||||||
// API配置字段绑定
|
// API配置字段绑定
|
||||||
const apiFields = [
|
const apiFields = [
|
||||||
{ id: 'amily2_jqyh_api_url', key: 'jqyhApiUrl' },
|
{ id: 'amily2_jqyh_api_url', key: 'jqyhApiUrl' },
|
||||||
{ id: 'amily2_jqyh_api_key', key: 'jqyhApiKey' },
|
{ id: 'amily2_jqyh_api_key', key: 'jqyhApiKey', sensitive: true },
|
||||||
{ id: 'amily2_jqyh_model', key: 'jqyhModel' }
|
{ id: 'amily2_jqyh_model', key: 'jqyhModel' }
|
||||||
];
|
];
|
||||||
|
|
||||||
apiFields.forEach(field => {
|
apiFields.forEach(field => {
|
||||||
const element = document.getElementById(field.id);
|
const element = document.getElementById(field.id);
|
||||||
if (element) {
|
if (element) {
|
||||||
element.value = extension_settings[extensionName][field.key] || '';
|
// 敏感字段(API Key)从 configManager(localStorage)读取
|
||||||
|
element.value = field.sensitive
|
||||||
|
? (configManager.get(field.key) || '')
|
||||||
|
: (extension_settings[extensionName][field.key] || '');
|
||||||
element.addEventListener('change', function() {
|
element.addEventListener('change', function() {
|
||||||
updateAndSaveSetting(field.key, this.value);
|
if (field.sensitive) {
|
||||||
|
configManager.set(field.key, this.value);
|
||||||
|
} else {
|
||||||
|
updateAndSaveSetting(field.key, this.value);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ import { testNccsApiConnection } from '../core/api/NccsApi.js';
|
|||||||
// 用于通过子元素定位父 block 的选择器
|
// 用于通过子元素定位父 block 的选择器
|
||||||
const BLOCK_SEL = '.amily2_settings_block, .control-group, .amily2_opt_settings_block';
|
const BLOCK_SEL = '.amily2_settings_block, .control-group, .amily2_opt_settings_block';
|
||||||
|
|
||||||
|
// 每个槽位在回填 Profile 值前的 DOM 字段快照(用于取消分配时还原)
|
||||||
|
// 结构:{ [slot]: { [selector]: value } }
|
||||||
|
const _fieldSnapshots = {};
|
||||||
|
|
||||||
const CARD_CLASS = 'amily2_profile_status_card';
|
const CARD_CLASS = 'amily2_profile_status_card';
|
||||||
const CARD_SLOT_ATTR = 'data-card-slot';
|
const CARD_SLOT_ATTR = 'data-card-slot';
|
||||||
const HIDDEN_ATTR = 'data-profile-hidden';
|
const HIDDEN_ATTR = 'data-profile-hidden';
|
||||||
@@ -115,11 +119,37 @@ export async function syncSlot(slot) {
|
|||||||
_removeCard(slot);
|
_removeCard(slot);
|
||||||
_restoreHidden(slot);
|
_restoreHidden(slot);
|
||||||
|
|
||||||
if (!profile) return;
|
if (!profile) {
|
||||||
|
// 取消分配:将 DOM 字段值还原为分配 Profile 前的快照,
|
||||||
|
// 防止残留的 Profile 回填值(尤其是 '••••••••' 的 Key 占位符)
|
||||||
|
// 因 blur 事件被误存入 extension_settings / localStorage。
|
||||||
|
const snap = _fieldSnapshots[slot];
|
||||||
|
if (snap) {
|
||||||
|
for (const [sel, val] of Object.entries(snap)) {
|
||||||
|
const el = document.querySelector(sel);
|
||||||
|
if (el) el.value = val;
|
||||||
|
}
|
||||||
|
delete _fieldSnapshots[slot];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const container = _resolveContainer(config.container);
|
const container = _resolveContainer(config.container);
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
|
// 回填前先快照各字段当前值(即 extension_settings / configManager 中的真实值),
|
||||||
|
// 以便取消分配时能还原,避免 Profile 值污染旧配置。
|
||||||
|
const snap = {};
|
||||||
|
for (const sel of Object.values(config.fields || {})) {
|
||||||
|
const el = document.querySelector(sel);
|
||||||
|
if (el) snap[sel] = el.value;
|
||||||
|
}
|
||||||
|
if (config.keyField) {
|
||||||
|
const keyEl = document.querySelector(config.keyField);
|
||||||
|
if (keyEl) snap[config.keyField] = keyEl.value;
|
||||||
|
}
|
||||||
|
_fieldSnapshots[slot] = snap;
|
||||||
|
|
||||||
// 回填值(向下兼容:部分代码仍从 DOM 读取 fallback)
|
// 回填值(向下兼容:部分代码仍从 DOM 读取 fallback)
|
||||||
for (const [key, sel] of Object.entries(config.fields || {})) {
|
for (const [key, sel] of Object.entries(config.fields || {})) {
|
||||||
const el = document.querySelector(sel);
|
const el = document.querySelector(sel);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { extension_settings } from "/scripts/extensions.js";
|
|||||||
import { characters, this_chid } from '/script.js';
|
import { characters, this_chid } from '/script.js';
|
||||||
import { extensionName, defaultSettings } from "../utils/settings.js";
|
import { extensionName, defaultSettings } from "../utils/settings.js";
|
||||||
import { pluginAuthStatus } from "../utils/auth.js";
|
import { pluginAuthStatus } from "../utils/auth.js";
|
||||||
|
import { configManager } from '../utils/config/ConfigManager.js';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -82,7 +83,7 @@ export function updateUI() {
|
|||||||
$("#amily2_api_provider").val(settings.apiProvider || 'openai');
|
$("#amily2_api_provider").val(settings.apiProvider || 'openai');
|
||||||
$("#amily2_api_url").val(settings.apiUrl);
|
$("#amily2_api_url").val(settings.apiUrl);
|
||||||
$("#amily2_api_url").attr('type', 'text');
|
$("#amily2_api_url").attr('type', 'text');
|
||||||
$("#amily2_api_key").val(settings.apiKey);
|
$("#amily2_api_key").val(configManager.get('apiKey') || '');
|
||||||
$("#amily2_model").val(settings.model);
|
$("#amily2_model").val(settings.model);
|
||||||
$("#amily2_preset_selector").val(settings.tavernProfile);
|
$("#amily2_preset_selector").val(settings.tavernProfile);
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { characters, this_chid, eventSource, event_types } from "/script.js";
|
|||||||
import { fetchNccsModels, testNccsApiConnection } from '../core/api/NccsApi.js';
|
import { fetchNccsModels, testNccsApiConnection } from '../core/api/NccsApi.js';
|
||||||
import { showGraphVisualization } from '../core/relationship-graph/visualizer.js';
|
import { showGraphVisualization } from '../core/relationship-graph/visualizer.js';
|
||||||
import { escapeHTML } from '../utils/utils.js';
|
import { escapeHTML } from '../utils/utils.js';
|
||||||
|
import { configManager } from '../utils/config/ConfigManager.js';
|
||||||
|
|
||||||
const isTouchDevice = () => window.matchMedia('(pointer: coarse)').matches;
|
const isTouchDevice = () => window.matchMedia('(pointer: coarse)').matches;
|
||||||
const getAllTablesContainer = () => document.getElementById('all-tables-container');
|
const getAllTablesContainer = () => document.getElementById('all-tables-container');
|
||||||
@@ -1994,7 +1995,6 @@ function bindNccsApiEvents() {
|
|||||||
if (settings.nccsFakeStreamEnabled === undefined) settings.nccsFakeStreamEnabled = false;
|
if (settings.nccsFakeStreamEnabled === undefined) settings.nccsFakeStreamEnabled = false;
|
||||||
if (settings.nccsApiMode === undefined) settings.nccsApiMode = 'openai_test';
|
if (settings.nccsApiMode === undefined) settings.nccsApiMode = 'openai_test';
|
||||||
if (settings.nccsApiUrl === undefined) settings.nccsApiUrl = 'https://api.openai.com/v1';
|
if (settings.nccsApiUrl === undefined) settings.nccsApiUrl = 'https://api.openai.com/v1';
|
||||||
if (settings.nccsApiKey === undefined) settings.nccsApiKey = '';
|
|
||||||
if (settings.nccsModel === undefined) settings.nccsModel = '';
|
if (settings.nccsModel === undefined) settings.nccsModel = '';
|
||||||
if (settings.nccsTavernProfile === undefined) settings.nccsTavernProfile = '';
|
if (settings.nccsTavernProfile === undefined) settings.nccsTavernProfile = '';
|
||||||
|
|
||||||
@@ -2015,7 +2015,7 @@ function bindNccsApiEvents() {
|
|||||||
enabledFakeStreamToggle.checked = settings.nccsFakeStreamEnabled;
|
enabledFakeStreamToggle.checked = settings.nccsFakeStreamEnabled;
|
||||||
if (modeSelect) modeSelect.value = settings.nccsApiMode;
|
if (modeSelect) modeSelect.value = settings.nccsApiMode;
|
||||||
if (urlInput) urlInput.value = settings.nccsApiUrl;
|
if (urlInput) urlInput.value = settings.nccsApiUrl;
|
||||||
if (keyInput) keyInput.value = settings.nccsApiKey;
|
if (keyInput) keyInput.value = configManager.get('nccsApiKey') || '';
|
||||||
if (modelInput) modelInput.value = settings.nccsModel;
|
if (modelInput) modelInput.value = settings.nccsModel;
|
||||||
if (presetSelect) presetSelect.value = settings.nccsTavernProfile || '';
|
if (presetSelect) presetSelect.value = settings.nccsTavernProfile || '';
|
||||||
|
|
||||||
@@ -2089,8 +2089,7 @@ function bindNccsApiEvents() {
|
|||||||
|
|
||||||
if (keyInput) {
|
if (keyInput) {
|
||||||
const saveKey = () => {
|
const saveKey = () => {
|
||||||
settings.nccsApiKey = keyInput.value;
|
configManager.set('nccsApiKey', keyInput.value);
|
||||||
saveSettingsDebounced();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
keyInput.addEventListener('blur', saveKey);
|
keyInput.addEventListener('blur', saveKey);
|
||||||
@@ -2144,11 +2143,11 @@ function bindNccsApiEvents() {
|
|||||||
|
|
||||||
if (urlInput) {
|
if (urlInput) {
|
||||||
settings.nccsApiUrl = urlInput.value;
|
settings.nccsApiUrl = urlInput.value;
|
||||||
|
saveSettingsDebounced();
|
||||||
}
|
}
|
||||||
if (keyInput) {
|
if (keyInput) {
|
||||||
settings.nccsApiKey = keyInput.value;
|
configManager.set('nccsApiKey', keyInput.value);
|
||||||
}
|
}
|
||||||
saveSettingsDebounced();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const models = await fetchNccsModels();
|
const models = await fetchNccsModels();
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
function a0_0x4566(_0x3c4bcd,_0x462ea4){_0x3c4bcd=_0x3c4bcd-0x8d;const _0x1fe670=a0_0x1fe6();let _0x45667d=_0x1fe670[_0x3c4bcd];if(a0_0x4566['TiiNjg']===undefined){var _0x619cb9=function(_0x96a409){const _0x2aec75='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x2fbd34='',_0x13f537='';for(let _0x127b81=0x0,_0x12d2a6,_0x2aa0a2,_0x386214=0x0;_0x2aa0a2=_0x96a409['charAt'](_0x386214++);~_0x2aa0a2&&(_0x12d2a6=_0x127b81%0x4?_0x12d2a6*0x40+_0x2aa0a2:_0x2aa0a2,_0x127b81++%0x4)?_0x2fbd34+=String['fromCharCode'](0xff&_0x12d2a6>>(-0x2*_0x127b81&0x6)):0x0){_0x2aa0a2=_0x2aec75['indexOf'](_0x2aa0a2);}for(let _0x28f7ec=0x0,_0x4831aa=_0x2fbd34['length'];_0x28f7ec<_0x4831aa;_0x28f7ec++){_0x13f537+='%'+('00'+_0x2fbd34['charCodeAt'](_0x28f7ec)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x13f537);};const _0x207ab0=function(_0x721ccd,_0x300873){let _0x5e8a5c=[],_0x1405a7=0x0,_0x3be183,_0x18a968='';_0x721ccd=_0x619cb9(_0x721ccd);let _0x58e1ab;for(_0x58e1ab=0x0;_0x58e1ab<0x100;_0x58e1ab++){_0x5e8a5c[_0x58e1ab]=_0x58e1ab;}for(_0x58e1ab=0x0;_0x58e1ab<0x100;_0x58e1ab++){_0x1405a7=(_0x1405a7+_0x5e8a5c[_0x58e1ab]+_0x300873['charCodeAt'](_0x58e1ab%_0x300873['length']))%0x100,_0x3be183=_0x5e8a5c[_0x58e1ab],_0x5e8a5c[_0x58e1ab]=_0x5e8a5c[_0x1405a7],_0x5e8a5c[_0x1405a7]=_0x3be183;}_0x58e1ab=0x0,_0x1405a7=0x0;for(let _0x460aff=0x0;_0x460aff<_0x721ccd['length'];_0x460aff++){_0x58e1ab=(_0x58e1ab+0x1)%0x100,_0x1405a7=(_0x1405a7+_0x5e8a5c[_0x58e1ab])%0x100,_0x3be183=_0x5e8a5c[_0x58e1ab],_0x5e8a5c[_0x58e1ab]=_0x5e8a5c[_0x1405a7],_0x5e8a5c[_0x1405a7]=_0x3be183,_0x18a968+=String['fromCharCode'](_0x721ccd['charCodeAt'](_0x460aff)^_0x5e8a5c[(_0x5e8a5c[_0x58e1ab]+_0x5e8a5c[_0x1405a7])%0x100]);}return _0x18a968;};a0_0x4566['VlxCUG']=_0x207ab0,a0_0x4566['lQXssB']={},a0_0x4566['TiiNjg']=!![];}const _0x4aafb8=_0x1fe670[0x0],_0x24d3b0=_0x3c4bcd+_0x4aafb8,_0x46e2c4=a0_0x4566['lQXssB'][_0x24d3b0];return!_0x46e2c4?(a0_0x4566['WogIJe']===undefined&&(a0_0x4566['WogIJe']=!![]),_0x45667d=a0_0x4566['VlxCUG'](_0x45667d,_0x462ea4),a0_0x4566['lQXssB'][_0x24d3b0]=_0x45667d):_0x45667d=_0x46e2c4,_0x45667d;}const a0_0x1b4874=a0_0x4566;(function(_0x50cc10,_0x361498){const _0x5ea55d=a0_0x4566,_0x1552f3=_0x50cc10();while(!![]){try{const _0x546ae9=parseInt(_0x5ea55d(0x99,'^H5X'))/0x1+-parseInt(_0x5ea55d(0xa7,'5Q$k'))/0x2*(parseInt(_0x5ea55d(0xa5,'5Q$k'))/0x3)+-parseInt(_0x5ea55d(0x91,'H1ui'))/0x4*(parseInt(_0x5ea55d(0x9d,'7$CC'))/0x5)+-parseInt(_0x5ea55d(0x9f,'$3XG'))/0x6+-parseInt(_0x5ea55d(0xa4,'5^jQ'))/0x7*(parseInt(_0x5ea55d(0x94,'9b%M'))/0x8)+parseInt(_0x5ea55d(0x8d,'5^jQ'))/0x9*(parseInt(_0x5ea55d(0x92,'(T!*'))/0xa)+parseInt(_0x5ea55d(0xa2,'@nIj'))/0xb*(parseInt(_0x5ea55d(0xa1,'gmKu'))/0xc);if(_0x546ae9===_0x361498)break;else _0x1552f3['push'](_0x1552f3['shift']());}catch(_0x5c3020){_0x1552f3['push'](_0x1552f3['shift']());}}}(a0_0x1fe6,0x7b4c5));export const SENSITIVE_KEYS=new Set([a0_0x1b4874(0x9b,'lD*1'),a0_0x1b4874(0xaa,'igl1'),a0_0x1b4874(0x93,'0$p4'),a0_0x1b4874(0xa3,'zygW'),a0_0x1b4874(0x95,'Z0Y4'),a0_0x1b4874(0x98,'XIj)'),a0_0x1b4874(0x97,'z5yh')]);function a0_0x1fe6(){const _0x1e1e6e=['WQpcUwuwuSkeWQxdTW','WPi6FvldO3VdNCoCjZRcOG','WQdcVHvVpSolWQNdRCkwtSotgq','W7VdUCkayaablCkE','WPe6Ev/dQWBcJSopeZBcP07cSG','kCkwW73cImkBq8kEW5FcMhfkWQTJWP0zxSkxxsXlW7lcP8oQxa','W5vXWR3dUCksWPyLpuBcRSkiW7FcHW','EgddH8kLgx0JWODFkW','omo1zWJdGSkmpmkVde4','amkMWQFcIIH3W7SRWRlcRG','W48+k8kMW40pF2e/WRpdOCkz','WRTHnXBcPdO4D2vNWQCuW4e','eZJcOe7dJ8oBF2vSWPNdKa','o8oAgMHcWOK3WOVcUrm','sv0PsmoztmoYgYxcOG','CbpdVSoiW5upWOqkW5ZdMq','et3cQGdcVCoquv5a','d8kenCkFW48oWQPNrY4','WPn0WOZcMrxcLCkCWOSilK4','WPPGtdhcKCk8x8khWQJcLG','WQtcSrnLoSopW7ZdHCkUsSoQoSkL','gbxdJmoPW6P3','tfGIsCowBCoZebZcSq','WQjrdMyaW4Hm','gbGptCk6W7TZ','B17dKCkWW6z2WOFdKdersmoHlq','yCkmtY9vWO4pWQRcKc4','d2JcMaFdHWHOW7JdP8kHW4PQya','d8keW7KiW7tdSuTDeq','a8oRW6tcLWXRk8keB8oV','EgxdGCkImuWJWQDJeG'];a0_0x1fe6=function(){return _0x1e1e6e;};return a0_0x1fe6();}
|
const a0_0x1479fa=a0_0x7f86;(function(_0x2e9516,_0x52aeec){const _0x429dd7=a0_0x7f86,_0x24e7c5=_0x2e9516();while(!![]){try{const _0x3c1c3e=-parseInt(_0x429dd7(0x191,'vApL'))/0x1*(parseInt(_0x429dd7(0x194,'HR*9'))/0x2)+-parseInt(_0x429dd7(0x19d,'ukkS'))/0x3+-parseInt(_0x429dd7(0x190,'xcc9'))/0x4*(-parseInt(_0x429dd7(0x19a,'HR*9'))/0x5)+-parseInt(_0x429dd7(0x18b,'z(lT'))/0x6*(parseInt(_0x429dd7(0x1a5,'%P4R'))/0x7)+parseInt(_0x429dd7(0x195,'9T43'))/0x8*(parseInt(_0x429dd7(0x189,']TSS'))/0x9)+-parseInt(_0x429dd7(0x196,'MMFL'))/0xa*(parseInt(_0x429dd7(0x18c,'HR*9'))/0xb)+parseInt(_0x429dd7(0x18f,'xGRA'))/0xc;if(_0x3c1c3e===_0x52aeec)break;else _0x24e7c5['push'](_0x24e7c5['shift']());}catch(_0x2e9e11){_0x24e7c5['push'](_0x24e7c5['shift']());}}}(a0_0x1639,0x91125));function a0_0x7f86(_0x34ffc7,_0x2ef194){_0x34ffc7=_0x34ffc7-0x186;const _0x163999=a0_0x1639();let _0x7f8655=_0x163999[_0x34ffc7];if(a0_0x7f86['lXhjGs']===undefined){var _0x3d2b89=function(_0x42a19f){const _0x345f7c='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0xb6f790='',_0x19aa87='';for(let _0x5957a3=0x0,_0x24ac51,_0x31290a,_0x1e8f0a=0x0;_0x31290a=_0x42a19f['charAt'](_0x1e8f0a++);~_0x31290a&&(_0x24ac51=_0x5957a3%0x4?_0x24ac51*0x40+_0x31290a:_0x31290a,_0x5957a3++%0x4)?_0xb6f790+=String['fromCharCode'](0xff&_0x24ac51>>(-0x2*_0x5957a3&0x6)):0x0){_0x31290a=_0x345f7c['indexOf'](_0x31290a);}for(let _0x3c8126=0x0,_0x223212=_0xb6f790['length'];_0x3c8126<_0x223212;_0x3c8126++){_0x19aa87+='%'+('00'+_0xb6f790['charCodeAt'](_0x3c8126)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x19aa87);};const _0x14803c=function(_0x255655,_0x4da8f8){let _0x286b75=[],_0x4a5098=0x0,_0x1b5194,_0x576d49='';_0x255655=_0x3d2b89(_0x255655);let _0x438503;for(_0x438503=0x0;_0x438503<0x100;_0x438503++){_0x286b75[_0x438503]=_0x438503;}for(_0x438503=0x0;_0x438503<0x100;_0x438503++){_0x4a5098=(_0x4a5098+_0x286b75[_0x438503]+_0x4da8f8['charCodeAt'](_0x438503%_0x4da8f8['length']))%0x100,_0x1b5194=_0x286b75[_0x438503],_0x286b75[_0x438503]=_0x286b75[_0x4a5098],_0x286b75[_0x4a5098]=_0x1b5194;}_0x438503=0x0,_0x4a5098=0x0;for(let _0x5994fa=0x0;_0x5994fa<_0x255655['length'];_0x5994fa++){_0x438503=(_0x438503+0x1)%0x100,_0x4a5098=(_0x4a5098+_0x286b75[_0x438503])%0x100,_0x1b5194=_0x286b75[_0x438503],_0x286b75[_0x438503]=_0x286b75[_0x4a5098],_0x286b75[_0x4a5098]=_0x1b5194,_0x576d49+=String['fromCharCode'](_0x255655['charCodeAt'](_0x5994fa)^_0x286b75[(_0x286b75[_0x438503]+_0x286b75[_0x4a5098])%0x100]);}return _0x576d49;};a0_0x7f86['uLnfVE']=_0x14803c,a0_0x7f86['VnBLHL']={},a0_0x7f86['lXhjGs']=!![];}const _0x2d157e=_0x163999[0x0],_0x4e93d9=_0x34ffc7+_0x2d157e,_0x57911d=a0_0x7f86['VnBLHL'][_0x4e93d9];return!_0x57911d?(a0_0x7f86['tQVguy']===undefined&&(a0_0x7f86['tQVguy']=!![]),_0x7f8655=a0_0x7f86['uLnfVE'](_0x7f8655,_0x2ef194),a0_0x7f86['VnBLHL'][_0x4e93d9]=_0x7f8655):_0x7f8655=_0x57911d,_0x7f8655;}function a0_0x1639(){const _0x1e2ebe=['sSkZArxcJLJcV8oqkI5A','W4/cMCkeo8kAW6jnWPRdPt4','uCoxu8oMtLPRWR7dKqa','o8kZiCk9W7LwW5/cGSoaAG','WQRdMdDBeeZcNKvbW4q3WQ/dVW','W4NdJNFdI8kzW5FcNKuszCk3qa','W44dz8oWWQJdNXdcHMC','nmkas8kEu3WkWQbCimkdEtmY','zaa4W5xcVb/cL0S','jCkxcmojvwBcR3RdOwddG0S','pWtcUCooygFcMxlcMCofWQ5psq','lSkxc8ohv2ZdVqRdP2ZdPfKvFW','WQZcGMSNucpdJq','ssZcVmkYW6DUW48oW7S','WOPSd1BdTIZcVCoQ','WPqpWRVdGCofF8oRWQ4jsG','W6ddGmkTW6RcL2H9WPK','WOpdUYNdLmkVhG','WQNdMJ9BfKZdSL9HW7SxWPC','W4SWoexdSd/cH8oIWQtcN8kWWRCAWPW','i8k3WPSSnvazAH51','WRuiySkUW5vaWP9eWOxcGmojWOddMq','kCorWRVdOM3dP1RcQ8kQWRhdT1dcTSoLiSkhDf3dK8onWO3cSqOY','W4z2WQRcHJb+fCoA','W5ddPYxdLCk8pue','l1BdHmolzSoxfdhcI8k1','WQZdMdLDrdddR0ntW5K','WRddL2XWxCo9WPxcUCoTCq','WPKHWP/cKJHTmSogC8kE','WQ7dR8oCnexcJmkwWRtcUmkF','D0v2vSkJWR3cJSkXbaa7yW','W5/dHeSRqCo/r8o+lHnupSk2'];a0_0x1639=function(){return _0x1e2ebe;};return a0_0x1639();}export const SENSITIVE_KEYS=new Set([a0_0x1479fa(0x199,'qH3w'),a0_0x1479fa(0x19b,'MMFL'),a0_0x1479fa(0x19e,'vsxg'),a0_0x1479fa(0x1a4,'wq5h'),a0_0x1479fa(0x19c,'Po[W'),a0_0x1479fa(0x18a,'LFk1'),a0_0x1479fa(0x188,'R#TN'),a0_0x1479fa(0x1a1,'oNoj')]);
|
||||||
@@ -997,65 +997,8 @@ export const defaultSettings = {
|
|||||||
|
|
||||||
|
|
||||||
export function validateSettings() {
|
export function validateSettings() {
|
||||||
const settings = extension_settings[extensionName] || {};
|
// 主 API 概念已移除,各功能模块通过 Profile 槽位或独立配置管理 API。
|
||||||
|
return null;
|
||||||
// 新版 Profile 系统管理 API 配置时,跳过旧版字段验证
|
|
||||||
const assignments = settings.amily2_profile_assignments || {};
|
|
||||||
if (assignments.main) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果启用了Ngms或Nccs,则跳过主API验证
|
|
||||||
if (settings.ngmsEnabled || settings.nccsEnabled) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const apiProvider = settings.apiProvider || 'openai';
|
|
||||||
const errors = [];
|
|
||||||
|
|
||||||
switch (apiProvider) {
|
|
||||||
case 'openai':
|
|
||||||
case 'openai_test':
|
|
||||||
if (!settings.apiUrl) {
|
|
||||||
errors.push("当前模式需要配置API URL");
|
|
||||||
} else if (!/^https?:\/\//.test(settings.apiUrl)) {
|
|
||||||
errors.push("API URL必须以http://或https://开头");
|
|
||||||
}
|
|
||||||
if (apiProvider === 'openai' && !settings.apiKey) {
|
|
||||||
errors.push("当前模式需要配置API Key");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'sillytavern_backend':
|
|
||||||
if (!settings.apiUrl) {
|
|
||||||
errors.push("SillyTavern后端模式需要配置API URL");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'google':
|
|
||||||
if (!settings.apiKey) {
|
|
||||||
errors.push("Google直连模式需要配置API Key");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'sillytavern_preset':
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (!settings.apiUrl) {
|
|
||||||
errors.push("API URL未配置");
|
|
||||||
}
|
|
||||||
if (!settings.apiKey) {
|
|
||||||
errors.push("API Key未配置");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!settings.model && apiProvider !== 'sillytavern_preset') {
|
|
||||||
errors.push("未选择模型");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings.maxTokens < 100 || settings.maxTokens > 100000) {
|
|
||||||
errors.push(`Token数超限 (${settings.maxTokens}) - 必须在100-100000之间`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors.length ? errors : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function saveSettings() {
|
export function saveSettings() {
|
||||||
|
|||||||
Reference in New Issue
Block a user