From 667a7827622fbea0e74efa33c45c300c437970da Mon Sep 17 00:00:00 2001
From: yyxyz0120 <295786908+yyxyz0120@users.noreply.github.com>
Date: Sat, 1 Aug 2026 00:33:09 +0800
Subject: [PATCH] feat(story-summary): add per-chat enable toggle
---
modules/story-summary/data/chat-toggle.js | 21 +++
modules/story-summary/story-summary-ui.js | 35 +++++
modules/story-summary/story-summary.html | 4 +
modules/story-summary/story-summary.js | 134 ++++++++++++++++--
.../story-summary/tests/chat-toggle.test.js | 35 +++++
package.json | 1 +
settings.html | 2 +-
7 files changed, 216 insertions(+), 16 deletions(-)
create mode 100644 modules/story-summary/data/chat-toggle.js
create mode 100644 modules/story-summary/tests/chat-toggle.test.js
diff --git a/modules/story-summary/data/chat-toggle.js b/modules/story-summary/data/chat-toggle.js
new file mode 100644
index 00000000..cca9c32d
--- /dev/null
+++ b/modules/story-summary/data/chat-toggle.js
@@ -0,0 +1,21 @@
+export const STORY_SUMMARY_CHAT_ENABLED_KEY = "storySummaryEnabled";
+
+export function getChatStorySummaryEnabled(chatMetadata, extensionId) {
+ if (!chatMetadata || typeof chatMetadata !== "object") return true;
+ const extensionMetadata = chatMetadata.extensions?.[extensionId];
+ return extensionMetadata?.[STORY_SUMMARY_CHAT_ENABLED_KEY] !== false;
+}
+
+export function setChatStorySummaryEnabled(chatMetadata, extensionId, enabled) {
+ if (!chatMetadata || typeof chatMetadata !== "object") {
+ throw new TypeError("chatMetadata must be an object");
+ }
+ chatMetadata.extensions ||= {};
+ chatMetadata.extensions[extensionId] ||= {};
+ chatMetadata.extensions[extensionId][STORY_SUMMARY_CHAT_ENABLED_KEY] = Boolean(enabled);
+ return chatMetadata.extensions[extensionId][STORY_SUMMARY_CHAT_ENABLED_KEY];
+}
+
+export function resolveStorySummaryEnabled(globalEnabled, chatEnabled) {
+ return Boolean(globalEnabled) && chatEnabled !== false;
+}
diff --git a/modules/story-summary/story-summary-ui.js b/modules/story-summary/story-summary-ui.js
index 5e6a3beb..3ee4ca3f 100644
--- a/modules/story-summary/story-summary-ui.js
+++ b/modules/story-summary/story-summary-ui.js
@@ -341,6 +341,7 @@
let timelineHasRenderedEvents = false;
let currentTimelineChatId = '';
let settingsSaveTimeoutId = null;
+ let currentChatSummaryEnabled = true;
let panelConfigLoadedFromServer = false;
let settingsOpenedWithServerConfig = false;
const pendingConfigSaveRequests = new Map();
@@ -444,6 +445,27 @@
}
}
+ function syncCurrentChatSummaryControls(enabled = currentChatSummaryEnabled) {
+ currentChatSummaryEnabled = enabled !== false;
+ const toggle = $('current-chat-enabled');
+ if (toggle) {
+ toggle.checked = currentChatSummaryEnabled;
+ toggle.disabled = false;
+ }
+
+ const generateButton = $('btn-generate');
+ if (generateButton) {
+ generateButton.disabled = !currentChatSummaryEnabled;
+ generateButton.title = currentChatSummaryEnabled ? '' : '请先启用当前聊天的剧情总结';
+ }
+
+ for (const id of ['hide-summarized', 'keep-visible-count', 'use-vector-boundary']) {
+ const control = $(id);
+ if (control) control.disabled = !currentChatSummaryEnabled;
+ }
+ syncVectorBoundaryControl(config.vector?.enabled, currentChatSummaryEnabled && config.ui.hideSummarized);
+ }
+
function syncAutoSummaryControls() {
const en = $('trigger-enabled');
const timing = $('trigger-timing');
@@ -2248,6 +2270,10 @@
const btn = $('btn-generate');
switch (d.type) {
+ case 'CHAT_SUMMARY_STATE':
+ syncCurrentChatSummaryControls(d.state?.effectiveEnabled !== false);
+ break;
+
case 'GENERATION_STATE':
localGenerating = !!d.isGenerating;
btn.textContent = localGenerating ? '停止' : '总结';
@@ -2566,6 +2592,14 @@
e.target.value = val;
};
+ // Current chat switch (saved immediately in chat metadata)
+ $('current-chat-enabled').onchange = e => {
+ const enabled = e.target.checked;
+ e.target.disabled = true;
+ syncCurrentChatSummaryControls(enabled);
+ postMsg('SET_CURRENT_CHAT_ENABLED', { enabled });
+ };
+
// Main actions
$('btn-clear').onclick = async () => {
const action = await showCleanActionMenu();
@@ -2705,6 +2739,7 @@
renderFacts([]);
bindEvents();
+ syncCurrentChatSummaryControls(currentChatSummaryEnabled);
// === THEME SWITCHER ===
(function () {
diff --git a/modules/story-summary/story-summary.html b/modules/story-summary/story-summary.html
index e464ca69..5338fa3c 100644
--- a/modules/story-summary/story-summary.html
+++ b/modules/story-summary/story-summary.html
@@ -88,6 +88,10 @@
剧情总结
+