Improve story summary assembly and UI

This commit is contained in:
2026-01-27 22:51:44 +08:00
parent 4043e120ae
commit 1dfa9f95f2
5 changed files with 266 additions and 124 deletions

View File

@@ -92,6 +92,9 @@ let eventsRegistered = false;
let vectorGenerating = false;
let vectorCancelled = false;
let hideApplyTimer = null;
const HIDE_APPLY_DEBOUNCE_MS = 250;
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
// ═══════════════════════════════════════════════════════════════════════════
@@ -583,11 +586,12 @@ async function sendSavedConfigToFrame() {
}
}
function sendFrameBaseData(store, totalFloors) {
const lastSummarized = store?.lastSummarizedMesId ?? -1;
const range = calcHideRange(lastSummarized);
const hiddenCount = range ? range.end + 1 : 0;
async function sendFrameBaseData(store, totalFloors) {
const boundary = await getHideBoundaryFloor(store);
const range = calcHideRange(boundary);
const hiddenCount = (store?.hideSummarizedHistory && range) ? (range.end + 1) : 0;
const lastSummarized = store?.lastSummarizedMesId ?? -1;
postToFrame({
type: "SUMMARY_BASE_DATA",
stats: {
@@ -629,7 +633,7 @@ function openPanelForMessage(mesId) {
const store = getSummaryStore();
const totalFloors = chat.length;
sendFrameBaseData(store, totalFloors);
sendFrameBaseData(store, totalFloors); // 不需要 awaitfire-and-forget
sendFrameFullData(store, totalFloors);
setSummaryGenerating(summaryGenerating);
@@ -641,6 +645,53 @@ function openPanelForMessage(mesId) {
sendLocalModelStatusToFrame(modelId);
}
// ═══════════════════════════════════════════════════════════════════════════
// Hide/Unhide向量模式联动"已总结"的定义切换)
// - 非向量boundary = lastSummarizedMesIdLLM总结边界
// - 向量boundary = meta.lastChunkFloor已向量化
// ═══════════════════════════════════════════════════════════════════════════
async function getHideBoundaryFloor(store) {
const vectorCfg = getVectorConfig();
if (!vectorCfg?.enabled) {
return store?.lastSummarizedMesId ?? -1;
}
const { chatId } = getContext();
if (!chatId) return -1;
const meta = await getMeta(chatId);
return meta?.lastChunkFloor ?? -1;
}
async function applyHideState() {
const store = getSummaryStore();
if (!store?.hideSummarizedHistory) return;
const boundary = await getHideBoundaryFloor(store);
if (boundary < 0) return;
const range = calcHideRange(boundary);
if (!range) return;
await executeSlashCommand(`/hide ${range.start}-${range.end}`);
}
function applyHideStateDebounced() {
clearTimeout(hideApplyTimer);
hideApplyTimer = setTimeout(() => {
applyHideState().catch((e) => xbLog.warn(MODULE_ID, "applyHideState failed", e));
}, HIDE_APPLY_DEBOUNCE_MS);
}
async function clearHideState() {
const store = getSummaryStore();
const boundary = await getHideBoundaryFloor(store);
if (boundary < 0) return;
await executeSlashCommand(`/unhide 0-${boundary}`);
}
// ═══════════════════════════════════════════════════════════════════════════
// 自动总结(保持原逻辑;不做 prompt 注入)
// ═══════════════════════════════════════════════════════════════════════════
@@ -849,18 +900,17 @@ function handleFrameMessage(event) {
case "TOGGLE_HIDE_SUMMARIZED": {
const store = getSummaryStore();
if (!store) break;
const lastSummarized = store.lastSummarizedMesId ?? -1;
if (lastSummarized < 0) break;
store.hideSummarizedHistory = !!data.enabled;
saveSummaryStore();
if (data.enabled) {
const range = calcHideRange(lastSummarized);
if (range) executeSlashCommand(`/hide ${range.start}-${range.end}`);
} else {
executeSlashCommand(`/unhide 0-${lastSummarized}`);
}
(async () => {
if (data.enabled) {
await applyHideState();
} else {
await clearHideState();
}
})();
break;
}
@@ -876,20 +926,15 @@ function handleFrameMessage(event) {
store.keepVisibleCount = newCount;
saveSummaryStore();
const lastSummarized = store.lastSummarizedMesId ?? -1;
if (store.hideSummarizedHistory && lastSummarized >= 0) {
(async () => {
await executeSlashCommand(`/unhide 0-${lastSummarized}`);
const range = calcHideRange(lastSummarized);
if (range) await executeSlashCommand(`/hide ${range.start}-${range.end}`);
const { chat } = getContext();
sendFrameBaseData(store, Array.isArray(chat) ? chat.length : 0);
})();
} else {
(async () => {
// 先清掉原隐藏,再按新 keepCount 重算隐藏
if (store.hideSummarizedHistory) {
await clearHideState();
await applyHideState();
}
const { chat } = getContext();
sendFrameBaseData(store, Array.isArray(chat) ? chat.length : 0);
}
await sendFrameBaseData(store, Array.isArray(chat) ? chat.length : 0);
})();
break;
}
@@ -924,8 +969,6 @@ async function handleManualGenerate(mesId, config) {
onStatus: (text) => postToFrame({ type: "SUMMARY_STATUS", statusText: text }),
onError: (msg) => postToFrame({ type: "SUMMARY_ERROR", message: msg }),
onComplete: ({ merged, endMesId }) => {
const store = getSummaryStore();
postToFrame({
type: "SUMMARY_FULL_DATA",
payload: {
@@ -943,12 +986,8 @@ async function handleManualGenerate(mesId, config) {
statusText: `已更新至 ${endMesId + 1} 楼 · ${merged.events?.length || 0} 个事件`,
});
// 隐藏逻辑(与注入无关
const lastSummarized = store?.lastSummarizedMesId ?? -1;
if (store?.hideSummarizedHistory && lastSummarized >= 0) {
const range = calcHideRange(lastSummarized);
if (range) executeSlashCommand(`/hide ${range.start}-${range.end}`);
}
// 隐藏逻辑:统一走 boundaryvector on/off 自动切换定义
applyHideStateDebounced();
updateFrameStatsAfterSummary(endMesId, merged);
},
@@ -969,15 +1008,10 @@ async function handleChatChanged() {
initButtonsForAll();
const store = getSummaryStore();
const lastSummarized = store?.lastSummarizedMesId ?? -1;
if (lastSummarized >= 0 && store?.hideSummarizedHistory === true) {
const range = calcHideRange(lastSummarized);
if (range) executeSlashCommand(`/hide ${range.start}-${range.end}`);
}
applyHideStateDebounced();
if (frameReady) {
sendFrameBaseData(store, newLength);
await sendFrameBaseData(store, newLength);
sendFrameFullData(store, newLength);
}
}
@@ -1009,6 +1043,9 @@ async function handleMessageReceived() {
await syncOnMessageReceived(chatId, lastFloor, message, vectorConfig);
await maybeAutoBuildChunks();
// 向量模式下lastChunkFloor 会持续推进;如果勾选隐藏,自动扩展隐藏范围
applyHideStateDebounced();
setTimeout(() => maybeAutoRunSummary("after_ai"), 1000);
}