From 8bf01e6ff3c13cb06eb121fcfed79cfad664e021 Mon Sep 17 00:00:00 2001 From: Youzini-afk <13153778771cx@gmail.com> Date: Fri, 10 Apr 2026 00:01:30 +0800 Subject: [PATCH] Tighten extraction persistence success gating --- index.js | 6 +++- maintenance/extraction-controller.js | 51 +++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index b34bb17..bd1d1b4 100644 --- a/index.js +++ b/index.js @@ -6505,7 +6505,11 @@ function updateProcessedHistorySnapshot(chat, lastProcessedAssistantFloor) { function shouldAdvanceProcessedHistory(batchStatus) { if (!batchStatus || typeof batchStatus !== "object") return false; - return batchStatus?.stages?.core?.outcome === "success"; + return ( + batchStatus?.stages?.core?.outcome === "success" && + batchStatus?.stages?.finalize?.outcome === "success" && + batchStatus?.completed === true + ); } function computePostProcessArtifacts( diff --git a/maintenance/extraction-controller.js b/maintenance/extraction-controller.js index 08fbe4d..8acd4b3 100644 --- a/maintenance/extraction-controller.js +++ b/maintenance/extraction-controller.js @@ -254,17 +254,61 @@ export async function executeExtractionBatchController( signal, batchStatus, ); - const finalizedBatchStatus = - effects?.batchStatus || - runtime.finalizeBatchStatus(batchStatus, runtime.getExtractionCount()); + const batchStatusRef = effects?.batchStatus || batchStatus; + const persistResult = runtime.saveGraphToChat({ + reason: "extraction-batch-complete", + persistMetadata: true, + captureShadow: true, + immediate: true, + }); + const persistAccepted = Boolean( + persistResult?.saved || persistResult?.queued, + ); + + if (!persistAccepted) { + runtime.setBatchStageOutcome( + batchStatusRef, + "finalize", + "failed", + `图谱持久化失败: ${persistResult?.reason || "unknown-persist-failure"}`, + ); + } + const finalizedBatchStatus = runtime.finalizeBatchStatus( + batchStatusRef, + runtime.getExtractionCount(), + ); runtime.getCurrentGraph().historyState.lastBatchStatus = { ...finalizedBatchStatus, historyAdvanced: runtime.shouldAdvanceProcessedHistory(finalizedBatchStatus), + persist: persistResult + ? { + saved: Boolean(persistResult.saved), + queued: Boolean(persistResult.queued), + blocked: Boolean(persistResult.blocked), + reason: String(persistResult.reason || ""), + saveMode: String(persistResult.saveMode || ""), + revision: Number.isFinite(Number(persistResult.revision)) + ? Number(persistResult.revision) + : 0, + } + : null, }; if (runtime.getCurrentGraph().historyState.lastBatchStatus.historyAdvanced) { runtime.updateProcessedHistorySnapshot(chat, endIdx); + } else if (!persistAccepted) { + runtime.setLastExtractionStatus( + "提取待恢复", + `楼层 ${startIdx}-${endIdx} 已抽取但未确认写盘成功,请稍后重试或检查持久化状态`, + "warning", + { syncRuntime: true }, + ); + runtime.console?.warn?.("[ST-BME] extraction persist not accepted", { + chatId: runtime.getGraphPersistenceState?.()?.chatId || "", + persist: persistResult, + processedRange: [startIdx, endIdx], + }); } const afterSnapshot = runtime.cloneGraphSnapshot(runtime.getCurrentGraph()); @@ -282,7 +326,6 @@ export async function executeExtractionBatchController( extractionCountBefore, }), ); - runtime.saveGraphToChat({ reason: "extraction-batch-complete" }); return { success: finalizedBatchStatus.completed,