mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 22:30:38 +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,
|
||||
onExportGraphController,
|
||||
onManualCompressController,
|
||||
onRebuildController,
|
||||
onTestEmbeddingController,
|
||||
onTestMemoryLLMController,
|
||||
onViewLastInjectionController,
|
||||
@@ -4492,99 +4493,32 @@ async function onViewGraph() {
|
||||
}
|
||||
|
||||
async function onRebuild() {
|
||||
if (!confirm("确定要从当前聊天重建图谱?这将清除现有图谱数据。")) return;
|
||||
if (!ensureGraphMutationReady("重建图谱")) return;
|
||||
|
||||
const context = getContext();
|
||||
const chat = context?.chat;
|
||||
if (!Array.isArray(chat)) {
|
||||
toastr.warning("当前聊天上下文不可用,无法重建");
|
||||
return;
|
||||
}
|
||||
|
||||
const previousGraphSnapshot = currentGraph
|
||||
? cloneGraphSnapshot(currentGraph)
|
||||
: cloneGraphSnapshot(
|
||||
normalizeGraphRuntimeState(createEmptyGraph(), getCurrentChatId()),
|
||||
);
|
||||
const previousUiState = snapshotRuntimeUiState();
|
||||
const settings = getSettings();
|
||||
setRuntimeStatus(
|
||||
"图谱重建中",
|
||||
`当前聊天 ${Array.isArray(chat) ? chat.length : 0} 条消息`,
|
||||
"running",
|
||||
);
|
||||
|
||||
currentGraph = normalizeGraphRuntimeState(
|
||||
createEmptyGraph(),
|
||||
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();
|
||||
}
|
||||
return await onRebuildController({
|
||||
buildRecoveryResult,
|
||||
clearHistoryDirty,
|
||||
clearInjectionState,
|
||||
cloneGraphSnapshot,
|
||||
confirm,
|
||||
createEmptyGraph,
|
||||
ensureGraphMutationReady,
|
||||
getContext,
|
||||
getCurrentChatId,
|
||||
getCurrentGraph: () => currentGraph,
|
||||
getSettings,
|
||||
normalizeGraphRuntimeState,
|
||||
prepareVectorStateForReplay,
|
||||
refreshPanelLiveState,
|
||||
replayExtractionFromHistory,
|
||||
restoreRuntimeUiState,
|
||||
saveGraphToChat,
|
||||
setCurrentGraph: (graph) => {
|
||||
currentGraph = graph;
|
||||
},
|
||||
setLastExtractionStatus,
|
||||
setRuntimeStatus,
|
||||
snapshotRuntimeUiState,
|
||||
toastr,
|
||||
});
|
||||
}
|
||||
|
||||
async function onManualCompress() {
|
||||
|
||||
@@ -4,6 +4,7 @@ import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import vm from "node:vm";
|
||||
import { onManualExtractController } from "../extraction-controller.js";
|
||||
import { onRebuildController } from "../ui-actions-controller.js";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const indexPath = path.resolve(__dirname, "../index.js");
|
||||
@@ -240,6 +241,7 @@ async function testManualRebuildSetsTerminalRuntimeStatus() {
|
||||
},
|
||||
saveGraphToChat() {},
|
||||
restoreRuntimeUiState() {},
|
||||
onRebuildController,
|
||||
result: null,
|
||||
};
|
||||
vm.createContext(context);
|
||||
|
||||
@@ -146,3 +146,102 @@ export async function onViewLastInjectionController(runtime) {
|
||||
|
||||
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