fix: delegate rebuild confirm to host globalThis wrapper

This commit is contained in:
Youzini-afk
2026-03-29 18:56:18 +08:00
parent b3b0b3a64c
commit ab37e2111c
2 changed files with 88 additions and 34 deletions

112
index.js
View File

@@ -1137,6 +1137,35 @@ function buildMessageRecallBadgeTitle(messageIndex, record) {
return lines.join("\n"); return lines.join("\n");
} }
function createMessageRecallBadgeElement(messageIndex, record) {
const badge = document.createElement("button");
badge.type = "button";
badge.className = "st-bme-recall-badge";
badge.textContent = "🧠";
badge.dataset.messageIndex = String(messageIndex);
badge.style.marginInlineStart = "6px";
badge.style.padding = "0 4px";
badge.style.borderRadius = "10px";
badge.style.border = "1px solid var(--SmartThemeBorderColor, #666)";
badge.style.background = "var(--SmartThemeQuoteColor, rgba(120, 120, 120, 0.18))";
badge.style.cursor = "pointer";
badge.style.fontSize = "12px";
badge.style.lineHeight = "1.4";
badge.addEventListener("click", (event) => {
event.preventDefault();
event.stopPropagation();
const indexFromDataset = Number.parseInt(badge.dataset.messageIndex, 10);
void onMessageRecallBadgeClick(
Number.isFinite(indexFromDataset) ? indexFromDataset : messageIndex,
);
});
badge.title = buildMessageRecallBadgeTitle(messageIndex, record);
badge.dataset.updatedAt = String(record?.updatedAt || "");
return badge;
}
function refreshPersistedRecallMessageUi() { function refreshPersistedRecallMessageUi() {
const context = getContext(); const context = getContext();
const chat = context?.chat; const chat = context?.chat;
@@ -1145,58 +1174,57 @@ function refreshPersistedRecallMessageUi() {
const chatRoot = document.getElementById("chat"); const chatRoot = document.getElementById("chat");
if (!chatRoot) return; if (!chatRoot) return;
chatRoot
.querySelectorAll?.(".st-bme-recall-badge")
?.forEach?.((badge) => badge.remove());
const messageElements = Array.from(chatRoot.querySelectorAll(".mes")); const messageElements = Array.from(chatRoot.querySelectorAll(".mes"));
for (let fallbackIndex = 0; fallbackIndex < messageElements.length; fallbackIndex++) { for (let fallbackIndex = 0; fallbackIndex < messageElements.length; fallbackIndex++) {
const messageElement = messageElements[fallbackIndex]; const messageElement = messageElements[fallbackIndex];
const messageIndex = resolveMessageIndexFromElement(messageElement, fallbackIndex); const messageIndex = resolveMessageIndexFromElement(messageElement, fallbackIndex);
if (!Number.isFinite(messageIndex)) continue; if (!Number.isFinite(messageIndex)) continue;
const existingBadges = Array.from(
messageElement.querySelectorAll?.(".st-bme-recall-badge") || [],
);
const existingBadge = existingBadges[0] || null;
for (let index = 1; index < existingBadges.length; index++) {
existingBadges[index].remove();
}
const message = chat[messageIndex]; const message = chat[messageIndex];
if (!message?.is_user) continue; if (!message?.is_user) {
existingBadge?.remove();
continue;
}
const record = readPersistedRecallFromUserMessage(chat, messageIndex); const record = readPersistedRecallFromUserMessage(chat, messageIndex);
if (!record?.injectionText) continue; if (!record?.injectionText) {
existingBadge?.remove();
continue;
}
const badge = document.createElement("button"); const badge = existingBadge || createMessageRecallBadgeElement(messageIndex, record);
badge.type = "button";
badge.className = "st-bme-recall-badge";
badge.textContent = "🧠";
badge.title = buildMessageRecallBadgeTitle(messageIndex, record);
badge.dataset.messageIndex = String(messageIndex); badge.dataset.messageIndex = String(messageIndex);
badge.style.marginInlineStart = "6px"; const nextUpdatedAt = String(record.updatedAt || "");
badge.style.padding = "0 4px"; if (badge.dataset.updatedAt !== nextUpdatedAt) {
badge.style.borderRadius = "10px"; badge.dataset.updatedAt = nextUpdatedAt;
badge.style.border = "1px solid var(--SmartThemeBorderColor, #666)"; badge.title = buildMessageRecallBadgeTitle(messageIndex, record);
badge.style.background = "var(--SmartThemeQuoteColor, rgba(120, 120, 120, 0.18))"; }
badge.style.cursor = "pointer";
badge.style.fontSize = "12px";
badge.style.lineHeight = "1.4";
badge.addEventListener("click", (event) => { if (!existingBadge) {
event.preventDefault(); const anchor =
event.stopPropagation(); messageElement.querySelector?.(".mes_buttons") ||
void onMessageRecallBadgeClick(messageIndex); messageElement.querySelector?.(".mes_title") ||
}); messageElement.querySelector?.(".mes_header") ||
messageElement;
const anchor = anchor.appendChild(badge);
messageElement.querySelector(".mes_buttons") || }
messageElement.querySelector(".mes_title") ||
messageElement.querySelector(".mes_header") ||
messageElement;
anchor.appendChild(badge);
} }
} }
function schedulePersistedRecallMessageUiRefresh(delayMs = 16) { function schedulePersistedRecallMessageUiRefresh(delayMs = 120) {
clearTimeout(persistedRecallUiRefreshTimer); clearTimeout(persistedRecallUiRefreshTimer);
persistedRecallUiRefreshTimer = setTimeout(() => { persistedRecallUiRefreshTimer = setTimeout(() => {
persistedRecallUiRefreshTimer = null; persistedRecallUiRefreshTimer = null;
refreshPersistedRecallMessageUi(); refreshPersistedRecallMessageUi();
}, Math.max(0, Number.parseInt(delayMs, 10) || 0)); }, Math.max(16, Number.parseInt(delayMs, 10) || 120));
} }
function showMessageRecallDetail(messageIndex, record) { function showMessageRecallDetail(messageIndex, record) {
@@ -2309,6 +2337,17 @@ function restoreRuntimeUiState(snapshot = {}) {
refreshPanelLiveState(); refreshPanelLiveState();
} }
function getLastProcessedAssistantFloor() {
const historyFloor = Number(currentGraph?.historyState?.lastProcessedAssistantFloor);
if (Number.isFinite(historyFloor)) {
return historyFloor;
}
const legacySeq = Number(currentGraph?.lastProcessedSeq);
if (Number.isFinite(legacySeq)) return legacySeq;
return -1;
}
async function recordGraphMutation({ async function recordGraphMutation({
beforeSnapshot, beforeSnapshot,
processedRange = null, processedRange = null,
@@ -4898,7 +4937,12 @@ async function onRebuild() {
clearHistoryDirty, clearHistoryDirty,
clearInjectionState, clearInjectionState,
cloneGraphSnapshot, cloneGraphSnapshot,
confirm, confirm: (message) => {
if (typeof globalThis.confirm === "function") {
return globalThis.confirm(message);
}
return false;
},
createEmptyGraph, createEmptyGraph,
ensureGraphMutationReady, ensureGraphMutationReady,
getContext, getContext,

View File

@@ -69,6 +69,13 @@ function createBaseStatusContext() {
}; };
} }
function testIndexDefinesLastProcessedAssistantFloorHelper() {
assert.match(
indexSource,
/function\s+getLastProcessedAssistantFloor\s*\(/,
);
}
async function testVectorSyncTerminalStateUpdatesRuntime() { async function testVectorSyncTerminalStateUpdatesRuntime() {
const context = { const context = {
...createBaseStatusContext(), ...createBaseStatusContext(),
@@ -191,6 +198,7 @@ async function testManualRebuildSetsTerminalRuntimeStatus() {
const chat = [{ is_user: true, mes: "u" }, { is_user: false, mes: "a" }]; const chat = [{ is_user: true, mes: "u" }, { is_user: false, mes: "a" }];
const context = { const context = {
...createBaseStatusContext(), ...createBaseStatusContext(),
__confirmHost: true,
currentGraph: { currentGraph: {
vectorIndexState: { vectorIndexState: {
lastWarning: "", lastWarning: "",
@@ -198,6 +206,7 @@ async function testManualRebuildSetsTerminalRuntimeStatus() {
batchJournal: [], batchJournal: [],
}, },
confirm() { confirm() {
assert.equal(this?.__confirmHost, true);
return true; return true;
}, },
ensureGraphMutationReady() { ensureGraphMutationReady() {
@@ -257,6 +266,7 @@ async function testManualRebuildSetsTerminalRuntimeStatus() {
assert.equal(context.runtimeStatus.level, "success"); assert.equal(context.runtimeStatus.level, "success");
} }
testIndexDefinesLastProcessedAssistantFloorHelper();
await testVectorSyncTerminalStateUpdatesRuntime(); await testVectorSyncTerminalStateUpdatesRuntime();
await testManualExtractNoBatchesDoesNotStayRunning(); await testManualExtractNoBatchesDoesNotStayRunning();
await testManualRebuildSetsTerminalRuntimeStatus(); await testManualRebuildSetsTerminalRuntimeStatus();