fix(story-summary): guard delayed handlers by chatId and use module event wrapper

This commit is contained in:
2026-02-12 17:01:44 +08:00
parent a646a70224
commit 40f59d6571

View File

@@ -10,7 +10,6 @@
import { getContext } from "../../../../../extensions.js"; import { getContext } from "../../../../../extensions.js";
import { import {
eventSource,
event_types, event_types,
extension_prompts, extension_prompts,
extension_prompt_types, extension_prompt_types,
@@ -18,6 +17,7 @@ import {
} from "../../../../../../script.js"; } 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 { createModuleEvents } from "../../core/event-manager.js";
import { postToIframe, isTrustedMessage } from "../../core/iframe-messaging.js"; import { postToIframe, isTrustedMessage } from "../../core/iframe-messaging.js";
import { CommonSettingStorage } from "../../core/server-storage.js"; import { CommonSettingStorage } from "../../core/server-storage.js";
@@ -111,7 +111,9 @@ let overlayCreated = false;
let frameReady = false; let frameReady = false;
let currentMesId = null; let currentMesId = null;
let pendingFrameMessages = []; let pendingFrameMessages = [];
let eventsRegistered = false; /** @type {ReturnType<typeof createModuleEvents>|null} */
let events = null;
let activeChatId = null;
let vectorCancelled = false; let vectorCancelled = false;
let vectorAbortController = null; let vectorAbortController = null;
@@ -1371,7 +1373,9 @@ async function handleManualGenerate(mesId, config) {
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════
async function handleChatChanged() { async function handleChatChanged() {
if (!events) return;
const { chat } = getContext(); const { chat } = getContext();
activeChatId = getContext().chatId || null;
const newLength = Array.isArray(chat) ? chat.length : 0; const newLength = Array.isArray(chat) ? chat.length : 0;
await rollbackSummaryIfNeeded(); await rollbackSummaryIfNeeded();
@@ -1405,7 +1409,8 @@ async function handleChatChanged() {
setTimeout(() => checkVectorIntegrityAndWarn(), 2000); setTimeout(() => checkVectorIntegrityAndWarn(), 2000);
} }
async function handleMessageDeleted() { async function handleMessageDeleted(scheduledChatId) {
if (isChatStale(scheduledChatId)) return;
const { chat, chatId } = getContext(); const { chat, chatId } = getContext();
const newLength = chat?.length || 0; const newLength = chat?.length || 0;
@@ -1426,7 +1431,8 @@ async function handleMessageDeleted() {
applyHideStateDebounced(); applyHideStateDebounced();
} }
async function handleMessageSwiped() { async function handleMessageSwiped(scheduledChatId) {
if (isChatStale(scheduledChatId)) return;
const { chat, chatId } = getContext(); const { chat, chatId } = getContext();
const lastFloor = (chat?.length || 1) - 1; const lastFloor = (chat?.length || 1) - 1;
@@ -1447,7 +1453,8 @@ async function handleMessageSwiped() {
await sendVectorStatsToFrame(); await sendVectorStatsToFrame();
} }
async function handleMessageReceived() { async function handleMessageReceived(scheduledChatId) {
if (isChatStale(scheduledChatId)) return;
const { chat, chatId } = getContext(); const { chat, chatId } = getContext();
const lastFloor = (chat?.length || 1) - 1; const lastFloor = (chat?.length || 1) - 1;
const message = chat?.[lastFloor]; const message = chat?.[lastFloor];
@@ -1480,12 +1487,14 @@ async function handleMessageReceived() {
setTimeout(() => maybeAutoExtractL0(), 2000); setTimeout(() => maybeAutoExtractL0(), 2000);
} }
function handleMessageSent() { function handleMessageSent(scheduledChatId) {
if (isChatStale(scheduledChatId)) return;
initButtonsForAll(); initButtonsForAll();
setTimeout(() => maybeAutoRunSummary("before_user"), 1000); setTimeout(() => maybeAutoRunSummary("before_user"), 1000);
} }
async function handleMessageUpdated() { async function handleMessageUpdated(scheduledChatId) {
if (isChatStale(scheduledChatId)) return;
await rollbackSummaryIfNeeded(); await rollbackSummaryIfNeeded();
initButtonsForAll(); initButtonsForAll();
applyHideStateDebounced(); applyHideStateDebounced();
@@ -1601,25 +1610,21 @@ async function handleGenerationStarted(type, _params, isDryRun) {
// 事件注册 // 事件注册
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════
const boundHandlers = { function scheduleWithChatGuard(fn, delay = 0) {
chatChanged: () => setTimeout(handleChatChanged, 80), const scheduledChatId = getContext().chatId;
messageDeleted: () => setTimeout(handleMessageDeleted, 50), setTimeout(() => fn(scheduledChatId), delay);
messageReceived: () => setTimeout(handleMessageReceived, 150), }
messageSent: () => setTimeout(handleMessageSent, 150),
messageSentRecall: handleMessageSentForRecall, function isChatStale(scheduledChatId) {
messageSwiped: () => setTimeout(handleMessageSwiped, 100), if (!scheduledChatId || scheduledChatId !== activeChatId) return true;
messageUpdated: () => setTimeout(handleMessageUpdated, 100), const { chatId } = getContext();
messageEdited: () => setTimeout(handleMessageUpdated, 100), return chatId !== scheduledChatId;
userRendered: (data) => setTimeout(() => handleMessageRendered(data), 50), }
charRendered: (data) => setTimeout(() => handleMessageRendered(data), 50),
genStarted: handleGenerationStarted,
genStopped: clearExtensionPrompt,
genEnded: clearExtensionPrompt,
};
function registerEvents() { function registerEvents() {
if (eventsRegistered) return; if (events) return;
eventsRegistered = true; events = createModuleEvents(MODULE_ID);
activeChatId = getContext().chatId || null;
CacheRegistry.register(MODULE_ID, { CacheRegistry.register(MODULE_ID, {
name: "待发送消息队列", name: "待发送消息队列",
@@ -1639,44 +1644,36 @@ function registerEvents() {
initButtonsForAll(); initButtonsForAll();
eventSource.on(event_types.CHAT_CHANGED, boundHandlers.chatChanged); events.on(event_types.CHAT_CHANGED, () => {
eventSource.on(event_types.MESSAGE_DELETED, boundHandlers.messageDeleted); activeChatId = getContext().chatId || null;
eventSource.on(event_types.MESSAGE_RECEIVED, boundHandlers.messageReceived); scheduleWithChatGuard(handleChatChanged, 80);
eventSource.on(event_types.MESSAGE_SENT, boundHandlers.messageSent); });
eventSource.on(event_types.MESSAGE_SENT, boundHandlers.messageSentRecall); events.on(event_types.MESSAGE_DELETED, () => scheduleWithChatGuard(handleMessageDeleted, 50));
eventSource.on(event_types.MESSAGE_SWIPED, boundHandlers.messageSwiped); events.on(event_types.MESSAGE_RECEIVED, () => scheduleWithChatGuard(handleMessageReceived, 150));
eventSource.on(event_types.MESSAGE_UPDATED, boundHandlers.messageUpdated); events.on(event_types.MESSAGE_SENT, () => scheduleWithChatGuard(handleMessageSent, 150));
eventSource.on(event_types.MESSAGE_EDITED, boundHandlers.messageEdited); events.on(event_types.MESSAGE_SENT, handleMessageSentForRecall);
eventSource.on(event_types.USER_MESSAGE_RENDERED, boundHandlers.userRendered); events.on(event_types.MESSAGE_SWIPED, () => scheduleWithChatGuard(handleMessageSwiped, 100));
eventSource.on(event_types.CHARACTER_MESSAGE_RENDERED, boundHandlers.charRendered); events.on(event_types.MESSAGE_UPDATED, () => scheduleWithChatGuard(handleMessageUpdated, 100));
events.on(event_types.MESSAGE_EDITED, () => scheduleWithChatGuard(handleMessageUpdated, 100));
events.on(event_types.USER_MESSAGE_RENDERED, (data) => setTimeout(() => handleMessageRendered(data), 50));
events.on(event_types.CHARACTER_MESSAGE_RENDERED, (data) => setTimeout(() => handleMessageRendered(data), 50));
// 用户输入捕获(原生捕获阶段) // 用户输入捕获(原生捕获阶段)
document.addEventListener("pointerdown", onSendPointerdown, true); document.addEventListener("pointerdown", onSendPointerdown, true);
document.addEventListener("keydown", onSendKeydown, true); document.addEventListener("keydown", onSendKeydown, true);
// 注入链路 // 注入链路
eventSource.on(event_types.GENERATION_STARTED, boundHandlers.genStarted); events.on(event_types.GENERATION_STARTED, handleGenerationStarted);
eventSource.on(event_types.GENERATION_STOPPED, boundHandlers.genStopped); events.on(event_types.GENERATION_STOPPED, clearExtensionPrompt);
eventSource.on(event_types.GENERATION_ENDED, boundHandlers.genEnded); events.on(event_types.GENERATION_ENDED, clearExtensionPrompt);
} }
function unregisterEvents() { function unregisterEvents() {
if (!events) return;
CacheRegistry.unregister(MODULE_ID); CacheRegistry.unregister(MODULE_ID);
eventsRegistered = false; events.cleanup();
events = null;
eventSource.off(event_types.CHAT_CHANGED, boundHandlers.chatChanged); activeChatId = null;
eventSource.off(event_types.MESSAGE_DELETED, boundHandlers.messageDeleted);
eventSource.off(event_types.MESSAGE_RECEIVED, boundHandlers.messageReceived);
eventSource.off(event_types.MESSAGE_SENT, boundHandlers.messageSent);
eventSource.off(event_types.MESSAGE_SENT, boundHandlers.messageSentRecall);
eventSource.off(event_types.MESSAGE_SWIPED, boundHandlers.messageSwiped);
eventSource.off(event_types.MESSAGE_UPDATED, boundHandlers.messageUpdated);
eventSource.off(event_types.MESSAGE_EDITED, boundHandlers.messageEdited);
eventSource.off(event_types.USER_MESSAGE_RENDERED, boundHandlers.userRendered);
eventSource.off(event_types.CHARACTER_MESSAGE_RENDERED, boundHandlers.charRendered);
eventSource.off(event_types.GENERATION_STARTED, boundHandlers.genStarted);
eventSource.off(event_types.GENERATION_STOPPED, boundHandlers.genStopped);
eventSource.off(event_types.GENERATION_ENDED, boundHandlers.genEnded);
$(".xiaobaix-story-summary-btn").remove(); $(".xiaobaix-story-summary-btn").remove();
hideOverlay(); hideOverlay();