Update TTS domain and adjust story summary injection

This commit is contained in:
2026-01-29 12:43:42 +08:00
parent 18ceff4c01
commit fc23781e17
5 changed files with 59 additions and 51 deletions

View File

@@ -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 VALID_EMOTIONS = ['happy', 'sad', 'angry', 'surprise', 'scare', 'hate'];
const EMOTION_ICONS = { const EMOTION_ICONS = {

View File

@@ -2,7 +2,7 @@
// 语音模块 - TTS 合成服务 // 语音模块 - 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_VOICE = 'female_1';
export const DEFAULT_SPEED = 1.0; export const DEFAULT_SPEED = 1.0;

View File

@@ -1,7 +1,7 @@
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════
// Story Summary - Prompt Injection (Final Clean Version) // Story Summary - Prompt Injection (Final Clean Version)
// - 仅负责“构建注入文本”,不负责写入 extension_prompts // - 仅负责“构建注入文本”,不负责写入 extension_prompts
// - 注入发生在 story-summary.js 的 CHAT_COMPLETION_PROMPT_READY最终 messages 已裁剪 // - 注入发生在 story-summary.jsGENERATION_STARTED 时写入 extension_promptsIN_CHAT + depth
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════
import { getContext } from "../../../../../../extensions.js"; import { getContext } from "../../../../../../extensions.js";

View File

@@ -6,11 +6,17 @@
// 2) 关闭隐藏 = 暴力全量 unhide确保立刻恢复 // 2) 关闭隐藏 = 暴力全量 unhide确保立刻恢复
// 3) 开启隐藏 / 改Y / 切Chat / 收新消息:先全量 unhide再按边界重新 hide // 3) 开启隐藏 / 改Y / 切Chat / 收新消息:先全量 unhide再按边界重新 hide
// 4) Prompt 注入位置稳定:永远插在"最后一条 user 消息"之前 // 4) Prompt 注入位置稳定:永远插在"最后一条 user 消息"之前
// 5) 注入不依赖 extension_prompts/depth不受 ST 裁剪/隐藏参照系影响 // 5) 注入回归 extension_prompts + IN_CHAT + depth动态计算
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════
import { getContext } from "../../../../../extensions.js"; 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 { extensionFolderPath } from "../../core/constants.js";
import { xbLog, CacheRegistry } from "../../core/debug-core.js"; import { xbLog, CacheRegistry } from "../../core/debug-core.js";
import { postToIframe, isTrustedMessage } from "../../core/iframe-messaging.js"; import { postToIframe, isTrustedMessage } from "../../core/iframe-messaging.js";
@@ -95,8 +101,6 @@ let vectorGenerating = false;
let vectorCancelled = false; let vectorCancelled = false;
let vectorAbortController = null; let vectorAbortController = null;
let pendingInjectText = "";
// ★ 用户消息缓存(解决 GENERATION_STARTED 时 chat 尚未包含用户消息的问题) // ★ 用户消息缓存(解决 GENERATION_STARTED 时 chat 尚未包含用户消息的问题)
let lastSentUserMessage = null; let lastSentUserMessage = null;
let lastSentTimestamp = 0; let lastSentTimestamp = 0;
@@ -106,6 +110,8 @@ const HIDE_APPLY_DEBOUNCE_MS = 250;
const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); 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 注入 // Prompt 注入
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════
@@ -1121,9 +1131,9 @@ async function handleGenerationStarted(type, _params, isDryRun) {
const excludeLastAi = type === "swipe" || type === "regenerate"; const excludeLastAi = type === "swipe" || type === "regenerate";
const vectorCfg = getVectorConfig(); const vectorCfg = getVectorConfig();
pendingInjectText = ""; clearExtensionPrompt();
// ★ 判断是否使用缓存的用户消息30秒内有效 // ★ 保留:判断是否使用缓存的用户消息30秒内有效
let pendingUserMessage = null; let pendingUserMessage = null;
if (type === "normal" && lastSentUserMessage && (Date.now() - lastSentTimestamp < 30000)) { if (type === "normal" && lastSentUserMessage && (Date.now() - lastSentTimestamp < 30000)) {
pendingUserMessage = lastSentUserMessage; pendingUserMessage = lastSentUserMessage;
@@ -1132,51 +1142,50 @@ async function handleGenerationStarted(type, _params, isDryRun) {
lastSentUserMessage = null; lastSentUserMessage = null;
lastSentTimestamp = 0; 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) { if (vectorCfg?.enabled) {
const r = await buildVectorPromptText(excludeLastAi, { const r = await buildVectorPromptText(excludeLastAi, {
postToFrame, postToFrame,
echo: executeSlashCommand, echo: executeSlashCommand,
pendingUserMessage, pendingUserMessage,
}); });
pendingInjectText = r?.text || ""; text = r?.text || "";
return; } else {
text = buildNonVectorPromptText() || "";
} }
if (!text.trim()) return;
pendingInjectText = buildNonVectorPromptText() || ""; // 4) 写入 extension_prompts
} extension_prompts[EXT_PROMPT_KEY] = {
value: text,
function clearPendingInject() { position: extension_prompt_types.IN_CHAT,
pendingInjectText = ""; depth,
} role: extension_prompt_roles.SYSTEM,
};
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();
}
} }
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════
@@ -1218,9 +1227,8 @@ function registerEvents() {
// 注入链路 // 注入链路
eventSource.on(event_types.GENERATION_STARTED, handleGenerationStarted); eventSource.on(event_types.GENERATION_STARTED, handleGenerationStarted);
eventSource.on(event_types.GENERATION_STOPPED, clearPendingInject); eventSource.on(event_types.GENERATION_STOPPED, clearExtensionPrompt);
eventSource.on(event_types.GENERATION_ENDED, clearPendingInject); eventSource.on(event_types.GENERATION_ENDED, clearExtensionPrompt);
eventSource.on(event_types.CHAT_COMPLETION_PROMPT_READY, handleChatCompletionPromptReady);
} }
function unregisterEvents() { function unregisterEvents() {
@@ -1230,7 +1238,7 @@ function unregisterEvents() {
$(".xiaobaix-story-summary-btn").remove(); $(".xiaobaix-story-summary-btn").remove();
hideOverlay(); hideOverlay();
clearPendingInject(); clearExtensionPrompt();
} }
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════

View File

@@ -4,7 +4,7 @@
*/ */
const V3_URL = 'https://openspeech.bytedance.com/api/v3/tts/unidirectional'; 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 = [ export const FREE_VOICES = [
{ key: 'female_1', name: '桃夭', tag: '甜蜜仙子', gender: 'female' }, { key: 'female_1', name: '桃夭', tag: '甜蜜仙子', gender: 'female' },