mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 14:20:35 +08:00
Fix processed history hash rebuild after recovery
This commit is contained in:
9
index.js
9
index.js
@@ -11609,6 +11609,14 @@ async function recoverHistoryIfNeeded(trigger = "history-recovery") {
|
||||
resultCode: "history.recovery.fallback-full-rebuild",
|
||||
}),
|
||||
);
|
||||
const recoveredLastProcessedFloor = Number.isFinite(
|
||||
currentGraph?.historyState?.lastProcessedAssistantFloor,
|
||||
)
|
||||
? currentGraph.historyState.lastProcessedAssistantFloor
|
||||
: -1;
|
||||
if (recoveredLastProcessedFloor >= 0) {
|
||||
updateProcessedHistorySnapshot(chat, recoveredLastProcessedFloor);
|
||||
}
|
||||
currentGraph.vectorIndexState.lastIntegrityIssue = null;
|
||||
saveGraphToChat({ reason: "history-recovery-fallback-rebuild" });
|
||||
refreshPanelLiveState();
|
||||
@@ -12390,6 +12398,7 @@ async function onRebuild() {
|
||||
replayExtractionFromHistory,
|
||||
restoreRuntimeUiState,
|
||||
saveGraphToChat,
|
||||
updateProcessedHistorySnapshot,
|
||||
setCurrentGraph: (graph) => {
|
||||
currentGraph = graph;
|
||||
},
|
||||
|
||||
@@ -257,6 +257,17 @@ export function normalizeGraphRuntimeState(graph, chatId = "") {
|
||||
historyState.processedMessageHashVersion = PROCESSED_MESSAGE_HASH_VERSION;
|
||||
historyState.processedMessageHashesNeedRefresh = true;
|
||||
}
|
||||
const lastProcessedAssistantFloor = Number(
|
||||
historyState.lastProcessedAssistantFloor,
|
||||
);
|
||||
if (
|
||||
historyState.processedMessageHashesNeedRefresh !== true &&
|
||||
Number.isFinite(lastProcessedAssistantFloor) &&
|
||||
lastProcessedAssistantFloor >= 0 &&
|
||||
Object.keys(historyState.processedMessageHashes).length === 0
|
||||
) {
|
||||
historyState.processedMessageHashesNeedRefresh = true;
|
||||
}
|
||||
|
||||
if (
|
||||
!vectorIndexState.hashToNodeId ||
|
||||
@@ -613,10 +624,15 @@ export function clearHistoryDirty(graph, result = null) {
|
||||
graph.historyState.historyDirtyFrom = null;
|
||||
graph.historyState.lastMutationReason = "";
|
||||
graph.historyState.lastMutationSource = "";
|
||||
const lastProcessedAssistantFloor = Number(
|
||||
graph.historyState.lastProcessedAssistantFloor,
|
||||
);
|
||||
graph.historyState.processedMessageHashVersion =
|
||||
PROCESSED_MESSAGE_HASH_VERSION;
|
||||
graph.historyState.processedMessageHashes = {};
|
||||
graph.historyState.processedMessageHashesNeedRefresh = false;
|
||||
graph.historyState.processedMessageHashesNeedRefresh =
|
||||
Number.isFinite(lastProcessedAssistantFloor) &&
|
||||
lastProcessedAssistantFloor >= 0;
|
||||
if (result) {
|
||||
graph.historyState.lastRecoveryResult = result;
|
||||
}
|
||||
|
||||
@@ -456,10 +456,17 @@ async function testManualExtractIgnoresFailedBatchWithoutPersistenceAttempt() {
|
||||
|
||||
async function testManualRebuildSetsTerminalRuntimeStatus() {
|
||||
const chat = [{ is_user: true, mes: "u" }, { is_user: false, mes: "a" }];
|
||||
let savedHashes = null;
|
||||
let savedNeedRefresh = null;
|
||||
const context = {
|
||||
...createBaseStatusContext(),
|
||||
__confirmHost: true,
|
||||
currentGraph: {
|
||||
historyState: {
|
||||
lastProcessedAssistantFloor: -1,
|
||||
processedMessageHashes: {},
|
||||
processedMessageHashesNeedRefresh: false,
|
||||
},
|
||||
vectorIndexState: {
|
||||
lastWarning: "",
|
||||
},
|
||||
@@ -489,6 +496,11 @@ async function testManualRebuildSetsTerminalRuntimeStatus() {
|
||||
},
|
||||
createEmptyGraph() {
|
||||
return {
|
||||
historyState: {
|
||||
lastProcessedAssistantFloor: -1,
|
||||
processedMessageHashes: {},
|
||||
processedMessageHashesNeedRefresh: false,
|
||||
},
|
||||
vectorIndexState: {
|
||||
lastWarning: "",
|
||||
},
|
||||
@@ -501,14 +513,31 @@ async function testManualRebuildSetsTerminalRuntimeStatus() {
|
||||
clearInjectionState() {},
|
||||
async prepareVectorStateForReplay() {},
|
||||
async replayExtractionFromHistory() {
|
||||
context.currentGraph.historyState.lastProcessedAssistantFloor = 1;
|
||||
context.currentGraph.vectorIndexState.lastWarning = "";
|
||||
return 2;
|
||||
},
|
||||
clearHistoryDirty() {},
|
||||
clearHistoryDirty(graph) {
|
||||
graph.historyState.processedMessageHashes = {};
|
||||
graph.historyState.processedMessageHashesNeedRefresh = true;
|
||||
},
|
||||
buildRecoveryResult(status, extra = {}) {
|
||||
return { status, ...extra };
|
||||
},
|
||||
saveGraphToChat() {},
|
||||
updateProcessedHistorySnapshot(chatInput, floor) {
|
||||
context.currentGraph.historyState.lastProcessedAssistantFloor = floor;
|
||||
context.currentGraph.historyState.processedMessageHashes = {};
|
||||
for (let index = 0; index <= floor; index += 1) {
|
||||
context.currentGraph.historyState.processedMessageHashes[index] =
|
||||
String(chatInput[index]?.mes || "");
|
||||
}
|
||||
context.currentGraph.historyState.processedMessageHashesNeedRefresh = false;
|
||||
},
|
||||
saveGraphToChat() {
|
||||
savedHashes = { ...context.currentGraph.historyState.processedMessageHashes };
|
||||
savedNeedRefresh =
|
||||
context.currentGraph.historyState.processedMessageHashesNeedRefresh;
|
||||
},
|
||||
restoreRuntimeUiState() {},
|
||||
onRebuildController,
|
||||
result: null,
|
||||
@@ -524,6 +553,11 @@ async function testManualRebuildSetsTerminalRuntimeStatus() {
|
||||
assert.equal(context.lastExtractionStatus.text, "图谱重建完成");
|
||||
assert.equal(context.runtimeStatus.text, "图谱重建完成");
|
||||
assert.equal(context.runtimeStatus.level, "success");
|
||||
assert.deepEqual(savedHashes, {
|
||||
0: "u",
|
||||
1: "a",
|
||||
});
|
||||
assert.equal(savedNeedRefresh, false);
|
||||
}
|
||||
|
||||
testIndexDefinesLastProcessedAssistantFloorHelper();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import assert from "node:assert/strict";
|
||||
import {
|
||||
appendBatchJournal,
|
||||
clearHistoryDirty,
|
||||
cloneGraphSnapshot,
|
||||
createBatchJournalEntry,
|
||||
detectHistoryMutation,
|
||||
@@ -95,6 +96,17 @@ assert.equal(migratedGraph.historyState.processedMessageHashesNeedRefresh, true)
|
||||
const migratedDetection = detectHistoryMutation(chat, migratedGraph.historyState);
|
||||
assert.equal(migratedDetection.dirty, false);
|
||||
|
||||
const emptyHashGraph = normalizeGraphRuntimeState({
|
||||
historyState: {
|
||||
chatId: "chat-history-test",
|
||||
lastProcessedAssistantFloor: 3,
|
||||
processedMessageHashVersion: PROCESSED_MESSAGE_HASH_VERSION,
|
||||
processedMessageHashes: {},
|
||||
processedMessageHashesNeedRefresh: false,
|
||||
},
|
||||
});
|
||||
assert.equal(emptyHashGraph.historyState.processedMessageHashesNeedRefresh, true);
|
||||
|
||||
const importedGraph = normalizeGraphRuntimeState({
|
||||
historyState: {
|
||||
chatId: "chat-history-test",
|
||||
@@ -117,6 +129,19 @@ assert.deepEqual(
|
||||
snapshotProcessedMessageHashes(chat, 3),
|
||||
);
|
||||
|
||||
const clearedGraph = normalizeGraphRuntimeState({
|
||||
historyState: {
|
||||
chatId: "chat-history-test",
|
||||
lastProcessedAssistantFloor: 3,
|
||||
processedMessageHashVersion: PROCESSED_MESSAGE_HASH_VERSION,
|
||||
processedMessageHashes: hashes,
|
||||
processedMessageHashesNeedRefresh: false,
|
||||
},
|
||||
});
|
||||
clearHistoryDirty(clearedGraph, { status: "replayed" });
|
||||
assert.deepEqual(clearedGraph.historyState.processedMessageHashes, {});
|
||||
assert.equal(clearedGraph.historyState.processedMessageHashesNeedRefresh, true);
|
||||
|
||||
const truncatedChat = chat.slice(0, 2);
|
||||
const truncatedDetection = detectHistoryMutation(truncatedChat, {
|
||||
lastProcessedAssistantFloor: 3,
|
||||
|
||||
@@ -415,6 +415,22 @@ export async function onRebuildController(runtime) {
|
||||
reason: "用户手动触发全量重建",
|
||||
}),
|
||||
);
|
||||
const recoveredLastProcessedFloor = Number.isFinite(
|
||||
runtime.getCurrentGraph()?.historyState?.lastProcessedAssistantFloor,
|
||||
)
|
||||
? runtime.getCurrentGraph().historyState.lastProcessedAssistantFloor
|
||||
: -1;
|
||||
if (recoveredLastProcessedFloor >= 0) {
|
||||
if (typeof runtime.updateProcessedHistorySnapshot === "function") {
|
||||
runtime.updateProcessedHistorySnapshot(chat, recoveredLastProcessedFloor);
|
||||
} else if (typeof runtime.applyProcessedHistorySnapshotToGraph === "function") {
|
||||
runtime.applyProcessedHistorySnapshotToGraph(
|
||||
runtime.getCurrentGraph(),
|
||||
chat,
|
||||
recoveredLastProcessedFloor,
|
||||
);
|
||||
}
|
||||
}
|
||||
runtime.saveGraphToChat({ reason: "manual-rebuild-complete" });
|
||||
runtime.setLastExtractionStatus(
|
||||
"图谱重建完成",
|
||||
|
||||
Reference in New Issue
Block a user