diff --git a/modules/fourth-wall/fourth-wall.html b/modules/fourth-wall/fourth-wall.html index 1178c9d..910cef9 100644 --- a/modules/fourth-wall/fourth-wall.html +++ b/modules/fourth-wall/fourth-wall.html @@ -561,7 +561,7 @@ html, body { 配置 ══════════════════════════════════════════════════════════════════════════════ */ -const TTS_WORKER_URL = 'https://hstts.velure.top'; +const TTS_WORKER_URL = 'https://hstts.velure.codes'; const VALID_EMOTIONS = ['happy', 'sad', 'angry', 'surprise', 'scare', 'hate']; const EMOTION_ICONS = { diff --git a/modules/fourth-wall/fw-voice.js b/modules/fourth-wall/fw-voice.js index 29b2bba..c1574c2 100644 --- a/modules/fourth-wall/fw-voice.js +++ b/modules/fourth-wall/fw-voice.js @@ -2,7 +2,7 @@ // 语音模块 - TTS 合成服务 // ════════════════════════════════════════════════════════════════════════════ -export const TTS_WORKER_URL = 'https://hstts.velure.top'; +export const TTS_WORKER_URL = 'https://hstts.velure.codes'; export const DEFAULT_VOICE = 'female_1'; export const DEFAULT_SPEED = 1.0; diff --git a/modules/story-summary/generate/prompt.js b/modules/story-summary/generate/prompt.js index fe51911..60ce9c5 100644 --- a/modules/story-summary/generate/prompt.js +++ b/modules/story-summary/generate/prompt.js @@ -1,7 +1,7 @@ // ═══════════════════════════════════════════════════════════════════════════ // Story Summary - Prompt Injection (Final Clean Version) // - 仅负责“构建注入文本”,不负责写入 extension_prompts -// - 注入发生在 story-summary.js 的 CHAT_COMPLETION_PROMPT_READY(最终 messages 已裁剪) +// - 注入发生在 story-summary.js:GENERATION_STARTED 时写入 extension_prompts(IN_CHAT + depth) // ═══════════════════════════════════════════════════════════════════════════ import { getContext } from "../../../../../../extensions.js"; diff --git a/modules/story-summary/story-summary.js b/modules/story-summary/story-summary.js index bfa0680..91f91f1 100644 --- a/modules/story-summary/story-summary.js +++ b/modules/story-summary/story-summary.js @@ -6,11 +6,17 @@ // 2) 关闭隐藏 = 暴力全量 unhide,确保立刻恢复 // 3) 开启隐藏 / 改Y / 切Chat / 收新消息:先全量 unhide,再按边界重新 hide // 4) Prompt 注入位置稳定:永远插在"最后一条 user 消息"之前 -// 5) 注入不依赖 extension_prompts/depth,不受 ST 裁剪/隐藏参照系影响 +// 5) 注入回归 extension_prompts + IN_CHAT + depth(动态计算) // ═══════════════════════════════════════════════════════════════════════════ import { getContext } from "../../../../../extensions.js"; -import { eventSource, event_types } from "../../../../../../script.js"; +import { + eventSource, + event_types, + extension_prompts, + extension_prompt_types, + extension_prompt_roles, +} from "../../../../../../script.js"; import { extensionFolderPath } from "../../core/constants.js"; import { xbLog, CacheRegistry } from "../../core/debug-core.js"; import { postToIframe, isTrustedMessage } from "../../core/iframe-messaging.js"; @@ -95,8 +101,6 @@ let vectorGenerating = false; let vectorCancelled = false; let vectorAbortController = null; -let pendingInjectText = ""; - // ★ 用户消息缓存(解决 GENERATION_STARTED 时 chat 尚未包含用户消息的问题) let lastSentUserMessage = null; let lastSentTimestamp = 0; @@ -106,6 +110,8 @@ const HIDE_APPLY_DEBOUNCE_MS = 250; const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); +const EXT_PROMPT_KEY = "LittleWhiteBox_StorySummary"; + // ═══════════════════════════════════════════════════════════════════════════ // 工具:执行斜杠命令 // ═══════════════════════════════════════════════════════════════════════════ @@ -1110,6 +1116,10 @@ function handleMessageSentForRecall() { } } +function clearExtensionPrompt() { + delete extension_prompts[EXT_PROMPT_KEY]; +} + // ═══════════════════════════════════════════════════════════════════════════ // Prompt 注入 // ═══════════════════════════════════════════════════════════════════════════ @@ -1121,9 +1131,9 @@ async function handleGenerationStarted(type, _params, isDryRun) { const excludeLastAi = type === "swipe" || type === "regenerate"; const vectorCfg = getVectorConfig(); - pendingInjectText = ""; + clearExtensionPrompt(); - // ★ 判断是否使用缓存的用户消息(30秒内有效) + // ★ 保留:判断是否使用缓存的用户消息(30秒内有效) let pendingUserMessage = null; if (type === "normal" && lastSentUserMessage && (Date.now() - lastSentTimestamp < 30000)) { pendingUserMessage = lastSentUserMessage; @@ -1132,51 +1142,50 @@ async function handleGenerationStarted(type, _params, isDryRun) { lastSentUserMessage = null; lastSentTimestamp = 0; + const { chat, chatId } = getContext(); + const chatLen = Array.isArray(chat) ? chat.length : 0; + if (chatLen === 0) return; + + const store = getSummaryStore(); + + // 1) boundary: + // - 向量开:meta.lastChunkFloor(若无则回退 lastSummarizedMesId) + // - 向量关:lastSummarizedMesId + let boundary = -1; + if (vectorCfg?.enabled) { + const meta = chatId ? await getMeta(chatId) : null; + boundary = meta?.lastChunkFloor ?? -1; + if (boundary < 0) boundary = store?.lastSummarizedMesId ?? -1; + } else { + boundary = store?.lastSummarizedMesId ?? -1; + } + if (boundary < 0) return; + + // 2) depth:倒序插入,从末尾往前数 + const depth = chatLen - boundary - 1; + if (depth < 0) return; + + // 3) 构建注入文本(保持原逻辑) + let text = ""; if (vectorCfg?.enabled) { const r = await buildVectorPromptText(excludeLastAi, { postToFrame, echo: executeSlashCommand, pendingUserMessage, }); - pendingInjectText = r?.text || ""; - return; + text = r?.text || ""; + } else { + text = buildNonVectorPromptText() || ""; } + if (!text.trim()) return; - pendingInjectText = buildNonVectorPromptText() || ""; -} - -function clearPendingInject() { - pendingInjectText = ""; -} - -function findInsertIndexBeforeLastUserMessage(chat) { - if (!Array.isArray(chat) || !chat.length) return 0; - for (let i = chat.length - 1; i >= 0; i--) { - if (chat[i]?.role === "user") return i; - } - // 没有 user,退化为末尾前一位 - return Math.max(0, chat.length - 1); -} - -function handleChatCompletionPromptReady(eventData) { - try { - if (!pendingInjectText?.trim()) return; - if (!eventData || eventData.dryRun) return; - if (!Array.isArray(eventData.chat)) return; - - // 永远插在最后一条 user 消息之前,保证三段结构稳定 - const insertAt = findInsertIndexBeforeLastUserMessage(eventData.chat); - - eventData.chat.splice(insertAt, 0, { - role: "assistant", - content: pendingInjectText, - }); - - clearPendingInject(); - } catch (e) { - xbLog.error(MODULE_ID, "Prompt inject failed", e); - clearPendingInject(); - } + // 4) 写入 extension_prompts + extension_prompts[EXT_PROMPT_KEY] = { + value: text, + position: extension_prompt_types.IN_CHAT, + depth, + role: extension_prompt_roles.SYSTEM, + }; } // ═══════════════════════════════════════════════════════════════════════════ @@ -1218,9 +1227,8 @@ function registerEvents() { // 注入链路 eventSource.on(event_types.GENERATION_STARTED, handleGenerationStarted); - eventSource.on(event_types.GENERATION_STOPPED, clearPendingInject); - eventSource.on(event_types.GENERATION_ENDED, clearPendingInject); - eventSource.on(event_types.CHAT_COMPLETION_PROMPT_READY, handleChatCompletionPromptReady); + eventSource.on(event_types.GENERATION_STOPPED, clearExtensionPrompt); + eventSource.on(event_types.GENERATION_ENDED, clearExtensionPrompt); } function unregisterEvents() { @@ -1230,7 +1238,7 @@ function unregisterEvents() { $(".xiaobaix-story-summary-btn").remove(); hideOverlay(); - clearPendingInject(); + clearExtensionPrompt(); } // ═══════════════════════════════════════════════════════════════════════════ diff --git a/modules/tts/tts-api.js b/modules/tts/tts-api.js index 858e579..7fb38cb 100644 --- a/modules/tts/tts-api.js +++ b/modules/tts/tts-api.js @@ -4,7 +4,7 @@ */ const V3_URL = 'https://openspeech.bytedance.com/api/v3/tts/unidirectional'; -const FREE_V1_URL = 'https://hstts.velure.top'; +const FREE_V1_URL = 'https://hstts.velure.codes'; export const FREE_VOICES = [ { key: 'female_1', name: '桃夭', tag: '甜蜜仙子', gender: 'female' },