mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-06-14 02:40:45 +08:00
refactor: move manual rebuild flow into ui actions controller
This commit is contained in:
120
index.js
120
index.js
@@ -80,6 +80,7 @@ import {
|
|||||||
onFetchMemoryLLMModelsController,
|
onFetchMemoryLLMModelsController,
|
||||||
onExportGraphController,
|
onExportGraphController,
|
||||||
onManualCompressController,
|
onManualCompressController,
|
||||||
|
onRebuildController,
|
||||||
onTestEmbeddingController,
|
onTestEmbeddingController,
|
||||||
onTestMemoryLLMController,
|
onTestMemoryLLMController,
|
||||||
onViewLastInjectionController,
|
onViewLastInjectionController,
|
||||||
@@ -4492,99 +4493,32 @@ async function onViewGraph() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function onRebuild() {
|
async function onRebuild() {
|
||||||
if (!confirm("确定要从当前聊天重建图谱?这将清除现有图谱数据。")) return;
|
return await onRebuildController({
|
||||||
if (!ensureGraphMutationReady("重建图谱")) return;
|
buildRecoveryResult,
|
||||||
|
clearHistoryDirty,
|
||||||
const context = getContext();
|
clearInjectionState,
|
||||||
const chat = context?.chat;
|
cloneGraphSnapshot,
|
||||||
if (!Array.isArray(chat)) {
|
confirm,
|
||||||
toastr.warning("当前聊天上下文不可用,无法重建");
|
createEmptyGraph,
|
||||||
return;
|
ensureGraphMutationReady,
|
||||||
}
|
getContext,
|
||||||
|
getCurrentChatId,
|
||||||
const previousGraphSnapshot = currentGraph
|
getCurrentGraph: () => currentGraph,
|
||||||
? cloneGraphSnapshot(currentGraph)
|
getSettings,
|
||||||
: cloneGraphSnapshot(
|
normalizeGraphRuntimeState,
|
||||||
normalizeGraphRuntimeState(createEmptyGraph(), getCurrentChatId()),
|
prepareVectorStateForReplay,
|
||||||
);
|
refreshPanelLiveState,
|
||||||
const previousUiState = snapshotRuntimeUiState();
|
replayExtractionFromHistory,
|
||||||
const settings = getSettings();
|
restoreRuntimeUiState,
|
||||||
setRuntimeStatus(
|
saveGraphToChat,
|
||||||
"图谱重建中",
|
setCurrentGraph: (graph) => {
|
||||||
`当前聊天 ${Array.isArray(chat) ? chat.length : 0} 条消息`,
|
currentGraph = graph;
|
||||||
"running",
|
},
|
||||||
);
|
setLastExtractionStatus,
|
||||||
|
setRuntimeStatus,
|
||||||
currentGraph = normalizeGraphRuntimeState(
|
snapshotRuntimeUiState,
|
||||||
createEmptyGraph(),
|
toastr,
|
||||||
getCurrentChatId(),
|
});
|
||||||
);
|
|
||||||
currentGraph.batchJournal = [];
|
|
||||||
clearInjectionState();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await prepareVectorStateForReplay(true);
|
|
||||||
const replayedBatches = await replayExtractionFromHistory(chat, settings);
|
|
||||||
clearHistoryDirty(
|
|
||||||
currentGraph,
|
|
||||||
buildRecoveryResult("full-rebuild", {
|
|
||||||
fromFloor: 0,
|
|
||||||
batches: replayedBatches,
|
|
||||||
path: "full-rebuild",
|
|
||||||
detectionSource: "manual-rebuild",
|
|
||||||
affectedBatchCount: currentGraph.batchJournal?.length || 0,
|
|
||||||
replayedBatchCount: replayedBatches,
|
|
||||||
reason: "用户手动触发全量重建",
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
saveGraphToChat({ reason: "manual-rebuild-complete" });
|
|
||||||
setLastExtractionStatus(
|
|
||||||
"图谱重建完成",
|
|
||||||
`已回放 ${replayedBatches} 批提取`,
|
|
||||||
"success",
|
|
||||||
{
|
|
||||||
syncRuntime: false,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (currentGraph.vectorIndexState?.lastWarning) {
|
|
||||||
setRuntimeStatus(
|
|
||||||
"图谱重建完成",
|
|
||||||
`已回放 ${replayedBatches} 批,但向量仍待修复`,
|
|
||||||
"warning",
|
|
||||||
);
|
|
||||||
toastr.warning(
|
|
||||||
`图谱已重建,但向量索引仍待修复: ${currentGraph.vectorIndexState.lastWarning}`,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
setRuntimeStatus(
|
|
||||||
"图谱重建完成",
|
|
||||||
`已回放 ${replayedBatches} 批,图谱与向量索引已刷新`,
|
|
||||||
"success",
|
|
||||||
);
|
|
||||||
toastr.success("图谱与向量索引已按当前聊天全量重建");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
currentGraph = normalizeGraphRuntimeState(
|
|
||||||
previousGraphSnapshot,
|
|
||||||
getCurrentChatId(),
|
|
||||||
);
|
|
||||||
restoreRuntimeUiState(previousUiState);
|
|
||||||
saveGraphToChat({ reason: "manual-rebuild-restore-previous" });
|
|
||||||
setLastExtractionStatus(
|
|
||||||
"图谱重建失败",
|
|
||||||
error?.message || String(error),
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
syncRuntime: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
throw new Error(
|
|
||||||
`图谱重建失败,已恢复到重建前状态: ${error?.message || error}`,
|
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
refreshPanelLiveState();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onManualCompress() {
|
async function onManualCompress() {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import path from "node:path";
|
|||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
import vm from "node:vm";
|
import vm from "node:vm";
|
||||||
import { onManualExtractController } from "../extraction-controller.js";
|
import { onManualExtractController } from "../extraction-controller.js";
|
||||||
|
import { onRebuildController } from "../ui-actions-controller.js";
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
const indexPath = path.resolve(__dirname, "../index.js");
|
const indexPath = path.resolve(__dirname, "../index.js");
|
||||||
@@ -240,6 +241,7 @@ async function testManualRebuildSetsTerminalRuntimeStatus() {
|
|||||||
},
|
},
|
||||||
saveGraphToChat() {},
|
saveGraphToChat() {},
|
||||||
restoreRuntimeUiState() {},
|
restoreRuntimeUiState() {},
|
||||||
|
onRebuildController,
|
||||||
result: null,
|
result: null,
|
||||||
};
|
};
|
||||||
vm.createContext(context);
|
vm.createContext(context);
|
||||||
|
|||||||
@@ -146,3 +146,102 @@ export async function onViewLastInjectionController(runtime) {
|
|||||||
|
|
||||||
runtime.document.body.appendChild(popup);
|
runtime.document.body.appendChild(popup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function onRebuildController(runtime) {
|
||||||
|
if (!runtime.confirm("确定要从当前聊天重建图谱?这将清除现有图谱数据。")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!runtime.ensureGraphMutationReady("重建图谱")) return;
|
||||||
|
|
||||||
|
const context = runtime.getContext();
|
||||||
|
const chat = context?.chat;
|
||||||
|
if (!Array.isArray(chat)) {
|
||||||
|
runtime.toastr.warning("当前聊天上下文不可用,无法重建");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const previousGraphSnapshot = runtime.getCurrentGraph()
|
||||||
|
? runtime.cloneGraphSnapshot(runtime.getCurrentGraph())
|
||||||
|
: runtime.cloneGraphSnapshot(
|
||||||
|
runtime.normalizeGraphRuntimeState(
|
||||||
|
runtime.createEmptyGraph(),
|
||||||
|
runtime.getCurrentChatId(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const previousUiState = runtime.snapshotRuntimeUiState();
|
||||||
|
const settings = runtime.getSettings();
|
||||||
|
runtime.setRuntimeStatus(
|
||||||
|
"图谱重建中",
|
||||||
|
`当前聊天 ${Array.isArray(chat) ? chat.length : 0} 条消息`,
|
||||||
|
"running",
|
||||||
|
);
|
||||||
|
|
||||||
|
const nextGraph = runtime.normalizeGraphRuntimeState(
|
||||||
|
runtime.createEmptyGraph(),
|
||||||
|
runtime.getCurrentChatId(),
|
||||||
|
);
|
||||||
|
nextGraph.batchJournal = [];
|
||||||
|
runtime.setCurrentGraph(nextGraph);
|
||||||
|
runtime.clearInjectionState();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await runtime.prepareVectorStateForReplay(true);
|
||||||
|
const replayedBatches = await runtime.replayExtractionFromHistory(chat, settings);
|
||||||
|
runtime.clearHistoryDirty(
|
||||||
|
runtime.getCurrentGraph(),
|
||||||
|
runtime.buildRecoveryResult("full-rebuild", {
|
||||||
|
fromFloor: 0,
|
||||||
|
batches: replayedBatches,
|
||||||
|
path: "full-rebuild",
|
||||||
|
detectionSource: "manual-rebuild",
|
||||||
|
affectedBatchCount: runtime.getCurrentGraph().batchJournal?.length || 0,
|
||||||
|
replayedBatchCount: replayedBatches,
|
||||||
|
reason: "用户手动触发全量重建",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
runtime.saveGraphToChat({ reason: "manual-rebuild-complete" });
|
||||||
|
runtime.setLastExtractionStatus(
|
||||||
|
"图谱重建完成",
|
||||||
|
`已回放 ${replayedBatches} 批提取`,
|
||||||
|
"success",
|
||||||
|
{
|
||||||
|
syncRuntime: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (runtime.getCurrentGraph().vectorIndexState?.lastWarning) {
|
||||||
|
runtime.setRuntimeStatus(
|
||||||
|
"图谱重建完成",
|
||||||
|
`已回放 ${replayedBatches} 批,但向量仍待修复`,
|
||||||
|
"warning",
|
||||||
|
);
|
||||||
|
runtime.toastr.warning(
|
||||||
|
`图谱已重建,但向量索引仍待修复: ${runtime.getCurrentGraph().vectorIndexState.lastWarning}`,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
runtime.setRuntimeStatus(
|
||||||
|
"图谱重建完成",
|
||||||
|
`已回放 ${replayedBatches} 批,图谱与向量索引已刷新`,
|
||||||
|
"success",
|
||||||
|
);
|
||||||
|
runtime.toastr.success("图谱与向量索引已按当前聊天全量重建");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
runtime.setCurrentGraph(
|
||||||
|
runtime.normalizeGraphRuntimeState(
|
||||||
|
previousGraphSnapshot,
|
||||||
|
runtime.getCurrentChatId(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
runtime.restoreRuntimeUiState(previousUiState);
|
||||||
|
runtime.saveGraphToChat({ reason: "manual-rebuild-restore-previous" });
|
||||||
|
runtime.setLastExtractionStatus("图谱重建失败", error?.message || String(error), "error", {
|
||||||
|
syncRuntime: true,
|
||||||
|
});
|
||||||
|
throw new Error(
|
||||||
|
`图谱重建失败,已恢复到重建前状态: ${error?.message || error}`,
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
runtime.refreshPanelLiveState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user