Files
LittleWhiteBox/index.js

670 lines
29 KiB
JavaScript
Raw Normal View History

2026-01-17 16:34:39 +08:00
import { extension_settings } from "../../../extensions.js";
import { saveSettingsDebounced, eventSource, event_types, getRequestHeaders } from "../../../../script.js";
import { EXT_ID, extensionFolderPath } from "./core/constants.js";
import { executeSlashCommand } from "./core/slash-command.js";
import { EventCenter } from "./core/event-manager.js";
import { initTasks } from "./modules/scheduled-tasks/scheduled-tasks.js";
import { initMessagePreview, addHistoryButtonsDebounced } from "./modules/message-preview.js";
import { initImmersiveMode } from "./modules/immersive-mode.js";
import { initTemplateEditor } from "./modules/template-editor/template-editor.js";
import { initFourthWall, fourthWallCleanup } from "./modules/fourth-wall/fourth-wall.js";
import { initButtonCollapse } from "./modules/button-collapse.js";
import { initVariablesPanel, cleanupVariablesPanel } from "./modules/variables/variables-panel.js";
import { initStreamingGeneration } from "./modules/streaming-generation.js";
import { initVariablesCore, cleanupVariablesCore } from "./modules/variables/variables-core.js";
import { initControlAudio } from "./modules/control-audio.js";
import {
initRenderer,
cleanupRenderer,
processExistingMessages,
clearBlobCaches,
renderHtmlInIframe,
shrinkRenderedWindowFull
} from "./modules/iframe-renderer.js";
import { initVarCommands, cleanupVarCommands } from "./modules/variables/var-commands.js";
import { initVareventEditor, cleanupVareventEditor } from "./modules/variables/varevent-editor.js";
import { initNovelDraw, cleanupNovelDraw } from "./modules/novel-draw/novel-draw.js";
import "./modules/story-summary/story-summary.js";
import "./modules/story-outline/story-outline.js";
import { initTts, cleanupTts } from "./modules/tts/tts.js";
extension_settings[EXT_ID] = extension_settings[EXT_ID] || {
enabled: true,
sandboxMode: false,
recorded: { enabled: true },
templateEditor: { enabled: true, characterBindings: {} },
tasks: { enabled: true, globalTasks: [], processedMessages: [], character_allowed_tasks: [] },
preview: { enabled: false },
immersive: { enabled: false },
fourthWall: { enabled: false },
audio: { enabled: true },
variablesPanel: { enabled: false },
variablesCore: { enabled: true },
storySummary: { enabled: true },
storyOutline: { enabled: false },
novelDraw: { enabled: false },
tts: { enabled: false },
useBlob: false,
wrapperIframe: true,
renderEnabled: true,
maxRenderedMessages: 5,
};
const settings = extension_settings[EXT_ID];
if (settings.dynamicPrompt && !settings.fourthWall) settings.fourthWall = settings.dynamicPrompt;
const DEPRECATED_KEYS = [
'characterUpdater',
'promptSections',
'promptPresets',
'relationshipGuidelines',
'scriptAssistant'
];
function cleanupDeprecatedData() {
const s = extension_settings[EXT_ID];
if (!s) return;
let cleaned = false;
for (const key of DEPRECATED_KEYS) {
if (key in s) {
delete s[key];
cleaned = true;
console.log(`[LittleWhiteBox] Cleaned deprecated data: ${key}`);
}
}
if (cleaned) {
saveSettingsDebounced();
console.log('[LittleWhiteBox] Deprecated data cleanup complete');
}
}
let isXiaobaixEnabled = settings.enabled;
let moduleCleanupFunctions = new Map();
let updateCheckPerformed = false;
window.isXiaobaixEnabled = isXiaobaixEnabled;
window.testLittleWhiteBoxUpdate = async () => {
updateCheckPerformed = false;
await performExtensionUpdateCheck();
};
window.testUpdateUI = () => {
updateExtensionHeaderWithUpdateNotice();
};
window.testRemoveUpdateUI = () => {
removeAllUpdateNotices();
};
async function checkLittleWhiteBoxUpdate() {
try {
const timestamp = Date.now();
const localRes = await fetch(`${extensionFolderPath}/manifest.json?t=${timestamp}`, { cache: 'no-cache' });
if (!localRes.ok) return null;
const localManifest = await localRes.json();
const localVersion = localManifest.version;
const remoteRes = await fetch(`https://api.github.com/repos/RT15548/LittleWhiteBox/contents/manifest.json?t=${timestamp}`, { cache: 'no-cache' });
if (!remoteRes.ok) return null;
const remoteData = await remoteRes.json();
const remoteManifest = JSON.parse(atob(remoteData.content));
const remoteVersion = remoteManifest.version;
return localVersion !== remoteVersion ? { isUpToDate: false, localVersion, remoteVersion } : { isUpToDate: true, localVersion, remoteVersion };
} catch (e) {
return null;
}
}
async function updateLittleWhiteBoxExtension() {
try {
const response = await fetch('/api/extensions/update', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({ extensionName: 'LittleWhiteBox', global: true }),
});
if (!response.ok) {
const text = await response.text();
toastr.error(text || response.statusText, 'LittleWhiteBox update failed', { timeOut: 5000 });
return false;
}
const data = await response.json();
const message = data.isUpToDate ? 'LittleWhiteBox is up to date' : `LittleWhiteBox updated`;
const title = data.isUpToDate ? '' : '请刷新页面以应用更新';
toastr.success(message, title);
return true;
} catch (error) {
toastr.error('Error during update', 'LittleWhiteBox update failed');
return false;
}
}
function updateExtensionHeaderWithUpdateNotice() {
addUpdateTextNotice();
addUpdateDownloadButton();
}
function addUpdateTextNotice() {
const selectors = [
'.inline-drawer-toggle.inline-drawer-header b',
'.inline-drawer-header b',
'.littlewhitebox .inline-drawer-header b',
'div[class*="inline-drawer"] b'
];
let headerElement = null;
for (const selector of selectors) {
const elements = document.querySelectorAll(selector);
for (const element of elements) {
if (element.textContent && element.textContent.includes('小白X')) {
headerElement = element;
break;
}
}
if (headerElement) break;
}
if (!headerElement) {
setTimeout(() => addUpdateTextNotice(), 1000);
return;
}
if (headerElement.querySelector('.littlewhitebox-update-text')) return;
const updateTextSmall = document.createElement('small');
updateTextSmall.className = 'littlewhitebox-update-text';
updateTextSmall.textContent = '(有可用更新)';
headerElement.appendChild(updateTextSmall);
}
function addUpdateDownloadButton() {
const sectionDividers = document.querySelectorAll('.section-divider');
let totalSwitchDivider = null;
for (const divider of sectionDividers) {
if (divider.textContent && divider.textContent.includes('总开关')) {
totalSwitchDivider = divider;
break;
}
}
if (!totalSwitchDivider) {
setTimeout(() => addUpdateDownloadButton(), 1000);
return;
}
if (document.querySelector('#littlewhitebox-update-extension')) return;
const updateButton = document.createElement('div');
updateButton.id = 'littlewhitebox-update-extension';
updateButton.className = 'menu_button fa-solid fa-cloud-arrow-down interactable has-update';
updateButton.title = '下载并安装小白X的更新';
updateButton.tabIndex = 0;
try {
totalSwitchDivider.style.display = 'flex';
totalSwitchDivider.style.alignItems = 'center';
totalSwitchDivider.style.justifyContent = 'flex-start';
} catch (e) {}
totalSwitchDivider.appendChild(updateButton);
try {
if (window.setupUpdateButtonInSettings) {
window.setupUpdateButtonInSettings();
}
} catch (e) {}
}
function removeAllUpdateNotices() {
const textNotice = document.querySelector('.littlewhitebox-update-text');
const downloadButton = document.querySelector('#littlewhitebox-update-extension');
if (textNotice) textNotice.remove();
if (downloadButton) downloadButton.remove();
}
async function performExtensionUpdateCheck() {
if (updateCheckPerformed) return;
updateCheckPerformed = true;
try {
const versionData = await checkLittleWhiteBoxUpdate();
if (versionData && versionData.isUpToDate === false) {
updateExtensionHeaderWithUpdateNotice();
}
} catch (error) {}
}
function registerModuleCleanup(moduleName, cleanupFunction) {
moduleCleanupFunctions.set(moduleName, cleanupFunction);
}
function removeSkeletonStyles() {
try {
document.querySelectorAll('.xiaobaix-skel').forEach(el => {
try { el.remove(); } catch (e) {}
});
document.getElementById('xiaobaix-skeleton-style')?.remove();
} catch (e) {}
}
function cleanupAllResources() {
try {
EventCenter.cleanupAll();
} catch (e) {}
try { window.xbDebugPanelClose?.(); } catch (e) {}
moduleCleanupFunctions.forEach((cleanupFn) => {
try {
cleanupFn();
} catch (e) {}
});
moduleCleanupFunctions.clear();
try {
cleanupRenderer();
} catch (e) {}
document.querySelectorAll('.memory-button, .mes_history_preview').forEach(btn => btn.remove());
document.querySelectorAll('#message_preview_btn').forEach(btn => {
if (btn instanceof HTMLElement) {
btn.style.display = 'none';
}
});
removeSkeletonStyles();
}
async function waitForElement(selector, root = document, timeout = 10000) {
const start = Date.now();
while (Date.now() - start < timeout) {
const element = root.querySelector(selector);
if (element) return element;
await new Promise(r => setTimeout(r, 100));
}
return null;
}
function toggleSettingsControls(enabled) {
const controls = [
'xiaobaix_sandbox', 'xiaobaix_recorded_enabled', 'xiaobaix_preview_enabled',
'scheduled_tasks_enabled', 'xiaobaix_template_enabled',
'xiaobaix_immersive_enabled', 'xiaobaix_fourth_wall_enabled',
'xiaobaix_audio_enabled', 'xiaobaix_variables_panel_enabled',
'xiaobaix_use_blob', 'xiaobaix_variables_core_enabled', 'Wrapperiframe', 'xiaobaix_render_enabled',
'xiaobaix_max_rendered', 'xiaobaix_story_outline_enabled', 'xiaobaix_story_summary_enabled',
'xiaobaix_novel_draw_enabled', 'xiaobaix_novel_draw_open_settings',
'xiaobaix_tts_enabled', 'xiaobaix_tts_open_settings'
];
controls.forEach(id => {
$(`#${id}`).prop('disabled', !enabled).closest('.flex-container').toggleClass('disabled-control', !enabled);
});
const styleId = 'xiaobaix-disabled-style';
if (!enabled && !document.getElementById(styleId)) {
const style = document.createElement('style');
style.id = styleId;
style.textContent = `.disabled-control, .disabled-control * { opacity: 0.4 !important; pointer-events: none !important; cursor: not-allowed !important; }`;
document.head.appendChild(style);
} else if (enabled) {
document.getElementById(styleId)?.remove();
}
}
async function toggleAllFeatures(enabled) {
if (enabled) {
toggleSettingsControls(true);
try { window.XB_applyPrevStates && window.XB_applyPrevStates(); } catch (e) {}
saveSettingsDebounced();
initRenderer();
try { initVarCommands(); } catch (e) {}
try { initVareventEditor(); } catch (e) {}
if (extension_settings[EXT_ID].tasks?.enabled) {
await initTasks();
}
const moduleInits = [
{ condition: extension_settings[EXT_ID].immersive?.enabled, init: initImmersiveMode },
{ condition: extension_settings[EXT_ID].templateEditor?.enabled, init: initTemplateEditor },
{ condition: extension_settings[EXT_ID].fourthWall?.enabled, init: initFourthWall },
{ condition: extension_settings[EXT_ID].variablesPanel?.enabled, init: initVariablesPanel },
{ condition: extension_settings[EXT_ID].variablesCore?.enabled, init: initVariablesCore },
{ condition: extension_settings[EXT_ID].novelDraw?.enabled, init: initNovelDraw },
{ condition: extension_settings[EXT_ID].tts?.enabled, init: initTts },
{ condition: true, init: initStreamingGeneration },
{ condition: true, init: initButtonCollapse }
];
moduleInits.forEach(({ condition, init }) => {
if (condition) init();
});
if (extension_settings[EXT_ID].preview?.enabled || extension_settings[EXT_ID].recorded?.enabled) {
setTimeout(initMessagePreview, 200);
}
if (extension_settings[EXT_ID].preview?.enabled)
setTimeout(() => { document.querySelectorAll('#message_preview_btn').forEach(btn => btn.style.display = ''); }, 500);
if (extension_settings[EXT_ID].recorded?.enabled)
setTimeout(() => addHistoryButtonsDebounced(), 600);
try {
if (isXiaobaixEnabled && settings.wrapperIframe && !document.getElementById('xb-callgen'))
document.head.appendChild(Object.assign(document.createElement('script'), { id: 'xb-callgen', type: 'module', src: `${extensionFolderPath}/bridges/call-generate-service.js` }));
} catch (e) {}
try {
if (isXiaobaixEnabled && !document.getElementById('xb-worldbook'))
document.head.appendChild(Object.assign(document.createElement('script'), { id: 'xb-worldbook', type: 'module', src: `${extensionFolderPath}/bridges/worldbook-bridge.js` }));
} catch (e) {}
document.dispatchEvent(new CustomEvent('xiaobaixEnabledChanged', { detail: { enabled: true } }));
$(document).trigger('xiaobaix:enabled:toggle', [true]);
} else {
try { window.XB_captureAndStoreStates && window.XB_captureAndStoreStates(); } catch (e) {}
cleanupAllResources();
if (window.messagePreviewCleanup) try { window.messagePreviewCleanup(); } catch (e) {}
if (window.fourthWallCleanup) try { window.fourthWallCleanup(); } catch (e) {}
if (window.buttonCollapseCleanup) try { window.buttonCollapseCleanup(); } catch (e) {}
try { cleanupVariablesPanel(); } catch (e) {}
try { cleanupVariablesCore(); } catch (e) {}
try { cleanupVarCommands(); } catch (e) {}
try { cleanupVareventEditor(); } catch (e) {}
try { cleanupNovelDraw(); } catch (e) {}
try { cleanupTts(); } catch (e) {}
try { clearBlobCaches(); } catch (e) {}
toggleSettingsControls(false);
try { window.cleanupWorldbookHostBridge && window.cleanupWorldbookHostBridge(); document.getElementById('xb-worldbook')?.remove(); } catch (e) {}
try { window.cleanupCallGenerateHostBridge && window.cleanupCallGenerateHostBridge(); document.getElementById('xb-callgen')?.remove(); } catch (e) {}
document.dispatchEvent(new CustomEvent('xiaobaixEnabledChanged', { detail: { enabled: false } }));
$(document).trigger('xiaobaix:enabled:toggle', [false]);
}
}
async function setupSettings() {
try {
const settingsContainer = await waitForElement("#extensions_settings");
if (!settingsContainer) return;
const response = await fetch(`${extensionFolderPath}/settings.html`);
const settingsHtml = await response.text();
$(settingsContainer).append(settingsHtml);
setupDebugButtonInSettings();
$("#xiaobaix_enabled").prop("checked", settings.enabled).on("change", async function () {
const wasEnabled = settings.enabled;
settings.enabled = $(this).prop("checked");
isXiaobaixEnabled = settings.enabled;
window.isXiaobaixEnabled = isXiaobaixEnabled;
saveSettingsDebounced();
if (settings.enabled !== wasEnabled) {
await toggleAllFeatures(settings.enabled);
}
});
if (!settings.enabled) toggleSettingsControls(false);
$("#xiaobaix_sandbox").prop("checked", settings.sandboxMode).on("change", async function () {
if (!isXiaobaixEnabled) return;
settings.sandboxMode = $(this).prop("checked");
saveSettingsDebounced();
});
const moduleConfigs = [
{ id: 'xiaobaix_recorded_enabled', key: 'recorded' },
{ id: 'xiaobaix_immersive_enabled', key: 'immersive', init: initImmersiveMode },
{ id: 'xiaobaix_preview_enabled', key: 'preview', init: initMessagePreview },
{ id: 'scheduled_tasks_enabled', key: 'tasks', init: initTasks },
{ id: 'xiaobaix_template_enabled', key: 'templateEditor', init: initTemplateEditor },
{ id: 'xiaobaix_fourth_wall_enabled', key: 'fourthWall', init: initFourthWall },
{ id: 'xiaobaix_variables_panel_enabled', key: 'variablesPanel', init: initVariablesPanel },
{ id: 'xiaobaix_variables_core_enabled', key: 'variablesCore', init: initVariablesCore },
{ id: 'xiaobaix_story_summary_enabled', key: 'storySummary' },
{ id: 'xiaobaix_story_outline_enabled', key: 'storyOutline' },
{ id: 'xiaobaix_novel_draw_enabled', key: 'novelDraw', init: initNovelDraw },
{ id: 'xiaobaix_tts_enabled', key: 'tts', init: initTts }
];
moduleConfigs.forEach(({ id, key, init }) => {
$(`#${id}`).prop("checked", settings[key]?.enabled || false).on("change", async function () {
if (!isXiaobaixEnabled) return;
const enabled = $(this).prop('checked');
if (!enabled && key === 'fourthWall') {
try { fourthWallCleanup(); } catch (e) {}
}
if (!enabled && key === 'novelDraw') {
try { cleanupNovelDraw(); } catch (e) {}
}
if (!enabled && key === 'tts') {
try { cleanupTts(); } catch (e) {}
}
settings[key] = extension_settings[EXT_ID][key] || {};
settings[key].enabled = enabled;
extension_settings[EXT_ID][key] = settings[key];
saveSettingsDebounced();
if (moduleCleanupFunctions.has(key)) {
moduleCleanupFunctions.get(key)();
moduleCleanupFunctions.delete(key);
}
if (enabled && init) await init();
if (key === 'storySummary') {
$(document).trigger('xiaobaix:storySummary:toggle', [enabled]);
}
if (key === 'storyOutline') {
$(document).trigger('xiaobaix:storyOutline:toggle', [enabled]);
}
});
});
$("#xiaobaix_novel_draw_open_settings").on("click", function () {
if (!isXiaobaixEnabled) return;
if (settings.novelDraw?.enabled && window.xiaobaixNovelDraw?.openSettings) {
window.xiaobaixNovelDraw.openSettings();
}
});
$("#xiaobaix_tts_open_settings").on("click", function () {
if (!isXiaobaixEnabled) return;
if (settings.tts?.enabled && window.xiaobaixTts?.openSettings) {
window.xiaobaixTts.openSettings();
} else {
toastr.warning('请先启用 TTS 语音模块');
}
});
$("#xiaobaix_use_blob").prop("checked", !!settings.useBlob).on("change", async function () {
if (!isXiaobaixEnabled) return;
settings.useBlob = $(this).prop("checked");
saveSettingsDebounced();
});
$("#Wrapperiframe").prop("checked", !!settings.wrapperIframe).on("change", async function () {
if (!isXiaobaixEnabled) return;
settings.wrapperIframe = $(this).prop("checked");
saveSettingsDebounced();
try {
settings.wrapperIframe
? (!document.getElementById('xb-callgen') && document.head.appendChild(Object.assign(document.createElement('script'), { id: 'xb-callgen', type: 'module', src: `${extensionFolderPath}/bridges/call-generate-service.js` })))
: (window.cleanupCallGenerateHostBridge && window.cleanupCallGenerateHostBridge(), document.getElementById('xb-callgen')?.remove());
} catch (e) {}
});
$("#xiaobaix_render_enabled").prop("checked", settings.renderEnabled !== false).on("change", async function () {
if (!isXiaobaixEnabled) return;
const wasEnabled = settings.renderEnabled !== false;
settings.renderEnabled = $(this).prop("checked");
saveSettingsDebounced();
if (!settings.renderEnabled && wasEnabled) {
cleanupRenderer();
} else if (settings.renderEnabled && !wasEnabled) {
initRenderer();
setTimeout(() => processExistingMessages(), 100);
}
});
const normalizeMaxRendered = (raw) => {
let v = parseInt(raw, 10);
if (!Number.isFinite(v) || v < 1) v = 1;
if (v > 9999) v = 9999;
return v;
};
$("#xiaobaix_max_rendered")
.val(Number.isFinite(settings.maxRenderedMessages) ? settings.maxRenderedMessages : 5)
.on("input change", function () {
if (!isXiaobaixEnabled) return;
const v = normalizeMaxRendered($(this).val());
$(this).val(v);
settings.maxRenderedMessages = v;
saveSettingsDebounced();
try { shrinkRenderedWindowFull(); } catch (e) {}
});
$(document).off('click.xbreset', '#xiaobaix_reset_btn').on('click.xbreset', '#xiaobaix_reset_btn', function (e) {
e.preventDefault();
e.stopPropagation();
const MAP = {
recorded: 'xiaobaix_recorded_enabled',
immersive: 'xiaobaix_immersive_enabled',
preview: 'xiaobaix_preview_enabled',
scriptAssistant: 'xiaobaix_script_assistant',
tasks: 'scheduled_tasks_enabled',
templateEditor: 'xiaobaix_template_enabled',
fourthWall: 'xiaobaix_fourth_wall_enabled',
variablesPanel: 'xiaobaix_variables_panel_enabled',
variablesCore: 'xiaobaix_variables_core_enabled',
novelDraw: 'xiaobaix_novel_draw_enabled',
tts: 'xiaobaix_tts_enabled'
};
const ON = ['templateEditor', 'tasks', 'variablesCore', 'audio', 'storySummary', 'recorded'];
const OFF = ['preview', 'immersive', 'variablesPanel', 'fourthWall', 'storyOutline', 'novelDraw', 'tts'];
function setChecked(id, val) {
const el = document.getElementById(id);
if (el) {
el.checked = !!val;
try { $(el).trigger('change'); } catch {}
}
}
ON.forEach(k => setChecked(MAP[k], true));
OFF.forEach(k => setChecked(MAP[k], false));
setChecked('xiaobaix_sandbox', false);
setChecked('xiaobaix_use_blob', false);
setChecked('Wrapperiframe', true);
try { saveSettingsDebounced(); } catch (e) {}
});
} catch (err) {}
}
function setupDebugButtonInSettings() {
try {
if (document.getElementById('xiaobaix-debug-btn')) return;
const enableCheckbox = document.getElementById('xiaobaix_enabled');
if (!enableCheckbox) {
setTimeout(setupDebugButtonInSettings, 800);
return;
}
const row = enableCheckbox.closest('.flex-container') || enableCheckbox.parentElement;
if (!row) return;
const btn = document.createElement('div');
btn.id = 'xiaobaix-debug-btn';
btn.className = 'menu_button';
btn.title = '切换调试监控';
btn.tabIndex = 0;
btn.style.marginLeft = 'auto';
btn.style.whiteSpace = 'nowrap';
btn.innerHTML = '<span class="dbg-light"></span><span>监控</span>';
const onActivate = async () => {
try {
const mod = await import('./modules/debug-panel/debug-panel.js');
if (mod?.toggleDebugPanel) await mod.toggleDebugPanel();
} catch (e) {}
};
btn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); onActivate(); });
btn.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); e.stopPropagation(); onActivate(); }
});
row.appendChild(btn);
} catch (e) {}
}
function setupMenuTabs() {
$(document).on('click', '.menu-tab', function () {
const targetId = $(this).attr('data-target');
$('.menu-tab').removeClass('active');
$('.settings-section').hide();
$(this).addClass('active');
$('.' + targetId).show();
});
setTimeout(() => {
$('.js-memory').show();
$('.task, .instructions').hide();
$('.menu-tab[data-target="js-memory"]').addClass('active');
$('.menu-tab[data-target="task"], .menu-tab[data-target="instructions"]').removeClass('active');
}, 300);
}
window.processExistingMessages = processExistingMessages;
window.renderHtmlInIframe = renderHtmlInIframe;
window.registerModuleCleanup = registerModuleCleanup;
window.updateLittleWhiteBoxExtension = updateLittleWhiteBoxExtension;
window.removeAllUpdateNotices = removeAllUpdateNotices;
jQuery(async () => {
try {
cleanupDeprecatedData();
isXiaobaixEnabled = settings.enabled;
window.isXiaobaixEnabled = isXiaobaixEnabled;
if (!document.getElementById('xiaobaix-skeleton-style')) {
const skelStyle = document.createElement('style');
skelStyle.id = 'xiaobaix-skeleton-style';
skelStyle.textContent = `.xiaobaix-iframe-wrapper{position:relative}`;
document.head.appendChild(skelStyle);
}
const response = await fetch(`${extensionFolderPath}/style.css`);
const styleElement = document.createElement('style');
styleElement.textContent = await response.text();
document.head.appendChild(styleElement);
await setupSettings();
try { initControlAudio(); } catch (e) {}
if (isXiaobaixEnabled) {
initRenderer();
}
try {
if (isXiaobaixEnabled && settings.wrapperIframe && !document.getElementById('xb-callgen'))
document.head.appendChild(Object.assign(document.createElement('script'), { id: 'xb-callgen', type: 'module', src: `${extensionFolderPath}/bridges/call-generate-service.js` }));
} catch (e) {}
try {
if (isXiaobaixEnabled && !document.getElementById('xb-worldbook'))
document.head.appendChild(Object.assign(document.createElement('script'), { id: 'xb-worldbook', type: 'module', src: `${extensionFolderPath}/bridges/worldbook-bridge.js` }));
} catch (e) {}
eventSource.on(event_types.APP_READY, () => {
setTimeout(performExtensionUpdateCheck, 2000);
});
if (isXiaobaixEnabled) {
try { initVarCommands(); } catch (e) {}
try { initVareventEditor(); } catch (e) {}
if (settings.tasks?.enabled) {
try { await initTasks(); } catch (e) { console.error('[Tasks] Init failed:', e); }
}
const moduleInits = [
{ condition: settings.immersive?.enabled, init: initImmersiveMode },
{ condition: settings.templateEditor?.enabled, init: initTemplateEditor },
{ condition: settings.fourthWall?.enabled, init: initFourthWall },
{ condition: settings.variablesPanel?.enabled, init: initVariablesPanel },
{ condition: settings.variablesCore?.enabled, init: initVariablesCore },
{ condition: settings.novelDraw?.enabled, init: initNovelDraw },
{ condition: settings.tts?.enabled, init: initTts },
{ condition: true, init: initStreamingGeneration },
{ condition: true, init: initButtonCollapse }
];
moduleInits.forEach(({ condition, init }) => { if (condition) init(); });
if (settings.preview?.enabled || settings.recorded?.enabled) {
setTimeout(initMessagePreview, 1500);
}
}
setTimeout(setupMenuTabs, 500);
setTimeout(() => {
if (window.messagePreviewCleanup) {
registerModuleCleanup('messagePreview', window.messagePreviewCleanup);
}
}, 2000);
setInterval(() => {
if (isXiaobaixEnabled) processExistingMessages();
}, 30000);
} catch (err) {}
});
export { executeSlashCommand };