mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 22:30:38 +08:00
feat(authority): add consistency repair actions
This commit is contained in:
97
index.js
97
index.js
@@ -2840,6 +2840,96 @@ async function restoreAuthorityCheckpointFromBlob(options = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
async function writeAuthorityCheckpointFromCurrentGraph(options = {}) {
|
||||
const settings = getSettings();
|
||||
const { capability } = getAuthorityRuntimeSnapshot(settings);
|
||||
const updatedAt = new Date().toISOString();
|
||||
const chatId = normalizeChatIdCandidate(
|
||||
options.chatId || getCurrentChatId() || graphPersistenceState.chatId || currentGraph?.chatId,
|
||||
);
|
||||
if (!chatId) {
|
||||
return {
|
||||
success: false,
|
||||
error: "missing-chat-id",
|
||||
};
|
||||
}
|
||||
if (!capability.blobReady || !shouldUseAuthorityBlobCheckpoint()) {
|
||||
return {
|
||||
success: false,
|
||||
error: "Authority Blob unavailable",
|
||||
};
|
||||
}
|
||||
|
||||
ensureCurrentGraphRuntimeState();
|
||||
if (!currentGraph) {
|
||||
return {
|
||||
success: false,
|
||||
error: "Authority runtime graph unavailable",
|
||||
};
|
||||
}
|
||||
|
||||
const revision = Math.max(
|
||||
1,
|
||||
Number(options.revision || 0),
|
||||
Number(currentGraph?.meta?.revision || 0),
|
||||
Number(getGraphPersistedRevision(currentGraph) || 0),
|
||||
Number(graphPersistenceState.revision || 0),
|
||||
);
|
||||
const integrity =
|
||||
normalizeChatIdCandidate(options.integrity) ||
|
||||
normalizeChatIdCandidate(getGraphPersistenceMeta(currentGraph)?.integrity) ||
|
||||
getChatMetadataIntegrity(getContext()) ||
|
||||
graphPersistenceState.metadataIntegrity;
|
||||
const reason = String(options.reason || "manual-authority-checkpoint");
|
||||
const checkpoint = buildLukerGraphCheckpointV2(currentGraph, {
|
||||
revision,
|
||||
chatId,
|
||||
integrity,
|
||||
reason,
|
||||
storageTier: "authority-sql-primary",
|
||||
persistedAt: updatedAt,
|
||||
});
|
||||
if (!checkpoint) {
|
||||
return {
|
||||
success: false,
|
||||
error: "Authority checkpoint payload unavailable",
|
||||
};
|
||||
}
|
||||
|
||||
const writeResult = await writeAuthorityLukerCheckpointBlob(checkpoint, {
|
||||
chatId,
|
||||
reason,
|
||||
signal: options.signal,
|
||||
});
|
||||
if (!writeResult?.ok) {
|
||||
return {
|
||||
success: false,
|
||||
error:
|
||||
writeResult?.error?.message ||
|
||||
writeResult?.reason ||
|
||||
"authority-blob-checkpoint-write-failed",
|
||||
};
|
||||
}
|
||||
|
||||
const auditResult = await runAuthorityConsistencyAudit({
|
||||
chatId,
|
||||
collectionId:
|
||||
normalizeChatIdCandidate(options.collectionId) ||
|
||||
normalizeChatIdCandidate(currentGraph?.vectorIndexState?.collectionId) ||
|
||||
buildVectorCollectionId(chatId),
|
||||
}).catch(() => null);
|
||||
return {
|
||||
success: true,
|
||||
result: {
|
||||
path: writeResult.path,
|
||||
revision,
|
||||
checkpointRevision: Number(checkpoint.revision || revision || 0),
|
||||
auditSummary: auditResult?.audit?.summary || null,
|
||||
auditActions: auditResult?.audit?.actions || [],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function submitAuthorityVectorRebuildJob({
|
||||
config = null,
|
||||
range = null,
|
||||
@@ -21404,6 +21494,12 @@ async function onRunAuthorityConsistencyAudit() {
|
||||
});
|
||||
}
|
||||
|
||||
async function onWriteAuthorityCheckpoint() {
|
||||
return await writeAuthorityCheckpointFromCurrentGraph({
|
||||
reason: "panel-authority-checkpoint-write",
|
||||
});
|
||||
}
|
||||
|
||||
async function onRestoreAuthorityCheckpoint() {
|
||||
return await restoreAuthorityCheckpointFromBlob({
|
||||
reason: "panel-authority-checkpoint-restore",
|
||||
@@ -21996,6 +22092,7 @@ async function onCompactLukerSidecar() {
|
||||
requeueAuthorityJob: async (jobId) => await requeueAuthorityJob(jobId),
|
||||
refreshAuthorityJobs: onRefreshAuthorityJobs,
|
||||
runAuthorityConsistencyAudit: onRunAuthorityConsistencyAudit,
|
||||
writeAuthorityCheckpoint: onWriteAuthorityCheckpoint,
|
||||
restoreAuthorityCheckpoint: onRestoreAuthorityCheckpoint,
|
||||
captureAuthorityPerformanceBaseline: onCaptureAuthorityPerformanceBaseline,
|
||||
reembedDirect: onReembedDirect,
|
||||
|
||||
@@ -145,5 +145,6 @@ assert.equal(auditDrift.summary.level, "warning");
|
||||
assert.ok(auditDrift.issues.some((issue) => issue.code === "sql-runtime-revision-drift"));
|
||||
assert.ok(auditDrift.issues.some((issue) => issue.code === "vector-dirty"));
|
||||
assert.ok(auditDrift.actions.includes("rebuild-authority-trivium"));
|
||||
assert.ok(auditDrift.actions.includes("write-authority-checkpoint"));
|
||||
|
||||
console.log("authority-consistency tests passed");
|
||||
|
||||
31
ui/panel.js
31
ui/panel.js
@@ -3248,13 +3248,27 @@ function _refreshTaskPersistence() {
|
||||
["诊断包时间", authorityBundleUpdatedLabel],
|
||||
["诊断包原因", ps.authorityDiagnosticsBundleReason || "—"],
|
||||
];
|
||||
const authorityAuditActions = Array.isArray(ps.authorityConsistencyAudit?.actions)
|
||||
? ps.authorityConsistencyAudit.actions.map((value) => String(value || "").trim()).filter(Boolean)
|
||||
: [];
|
||||
const showAuthorityCheckpointWriteAction =
|
||||
authorityAuditActions.includes("write-authority-checkpoint") ||
|
||||
(!ps.authorityBlobCheckpointPath && ps.authorityBlobReady);
|
||||
const showAuthorityTriviumRebuildAction =
|
||||
authorityAuditActions.includes("rebuild-authority-trivium");
|
||||
const authorityActionButtons = [
|
||||
typeof _actionHandlers.runAuthorityConsistencyAudit === "function"
|
||||
? `<button class="bme-config-secondary-btn" type="button" data-authority-persistence-action="audit">执行 Authority 审计</button>`
|
||||
: "",
|
||||
showAuthorityCheckpointWriteAction && typeof _actionHandlers.writeAuthorityCheckpoint === "function"
|
||||
? `<button class="bme-config-secondary-btn" type="button" data-authority-persistence-action="checkpoint">写入当前 Checkpoint</button>`
|
||||
: "",
|
||||
typeof _actionHandlers.restoreAuthorityCheckpoint === "function"
|
||||
? `<button class="bme-config-secondary-btn" type="button" data-authority-persistence-action="restore">从 Checkpoint 恢复</button>`
|
||||
: "",
|
||||
showAuthorityTriviumRebuildAction && typeof _actionHandlers.rebuildVectorIndex === "function"
|
||||
? `<button class="bme-config-secondary-btn" type="button" data-authority-persistence-action="rebuild-trivium">重建 Authority Trivium</button>`
|
||||
: "",
|
||||
typeof _actionHandlers.captureAuthorityPerformanceBaseline === "function"
|
||||
? `<button class="bme-config-secondary-btn" type="button" data-authority-persistence-action="baseline">捕获 Perf Baseline</button>`
|
||||
: "",
|
||||
@@ -3321,6 +3335,15 @@ function _refreshTaskPersistence() {
|
||||
} else {
|
||||
toastr.warning(`Authority 审计失败:${result?.error || "unknown"}`, "ST-BME");
|
||||
}
|
||||
} else if (action === "checkpoint") {
|
||||
if (typeof _actionHandlers.writeAuthorityCheckpoint !== "function") return;
|
||||
toastr.info("Authority Checkpoint 写入中…", "ST-BME", { timeOut: 2000 });
|
||||
const result = await _actionHandlers.writeAuthorityCheckpoint();
|
||||
if (result?.success) {
|
||||
toastr.success(`Authority Checkpoint 已写入:rev ${Number(result?.result?.checkpointRevision || result?.result?.revision || 0) || "?"}`, "ST-BME");
|
||||
} else {
|
||||
toastr.warning(`Authority Checkpoint 写入失败:${result?.error || "unknown"}`, "ST-BME");
|
||||
}
|
||||
} else if (action === "restore") {
|
||||
if (typeof _actionHandlers.restoreAuthorityCheckpoint !== "function") return;
|
||||
toastr.info("Authority Checkpoint 恢复中…", "ST-BME", { timeOut: 2000 });
|
||||
@@ -3330,6 +3353,10 @@ function _refreshTaskPersistence() {
|
||||
} else {
|
||||
toastr.warning(`Authority Checkpoint 恢复失败:${result?.error || "unknown"}`, "ST-BME");
|
||||
}
|
||||
} else if (action === "rebuild-trivium") {
|
||||
if (typeof _actionHandlers.rebuildVectorIndex !== "function") return;
|
||||
await _actionHandlers.rebuildVectorIndex();
|
||||
return;
|
||||
} else if (action === "baseline") {
|
||||
if (typeof _actionHandlers.captureAuthorityPerformanceBaseline !== "function") return;
|
||||
const result = await _actionHandlers.captureAuthorityPerformanceBaseline();
|
||||
@@ -3349,6 +3376,10 @@ function _refreshTaskPersistence() {
|
||||
toastr.error(
|
||||
action === "restore"
|
||||
? `Authority Checkpoint 恢复失败: ${error?.message || error}`
|
||||
: action === "checkpoint"
|
||||
? `Authority Checkpoint 写入失败: ${error?.message || error}`
|
||||
: action === "rebuild-trivium"
|
||||
? `Authority Trivium 重建失败: ${error?.message || error}`
|
||||
: action === "baseline"
|
||||
? `Authority Perf Baseline 捕获失败: ${error?.message || error}`
|
||||
: `Authority 审计失败: ${error?.message || error}`,
|
||||
|
||||
Reference in New Issue
Block a user