diff --git a/index.js b/index.js index 5665790..de015db 100644 --- a/index.js +++ b/index.js @@ -5603,7 +5603,11 @@ async function refreshRuntimeGraphAfterSyncApplied(syncPayload = {}) { const action = String(syncPayload?.action || "") .trim() .toLowerCase(); - if (action !== "download" && action !== "merge") { + if ( + action !== "download" && + action !== "merge" && + action !== "restore-backup" + ) { return { refreshed: false, reason: "action-not-supported", diff --git a/tests/graph-persistence.mjs b/tests/graph-persistence.mjs index db52940..11bdc17 100644 --- a/tests/graph-persistence.mjs +++ b/tests/graph-persistence.mjs @@ -1947,6 +1947,51 @@ result = { ); } +{ + const harness = await createGraphPersistenceHarness({ + chatId: "chat-sync-refresh-restore", + chatMetadata: { + integrity: "chat-sync-refresh-restore-ready", + }, + }); + harness.api.setCurrentGraph( + normalizeGraphRuntimeState( + createMeaningfulGraph("chat-sync-refresh-restore", "stale-runtime-restore"), + "chat-sync-refresh-restore", + ), + ); + harness.api.setGraphPersistenceState({ + loadState: "loaded", + chatId: "chat-sync-refresh-restore", + reason: "runtime-stale", + revision: 5, + lastPersistedRevision: 5, + dbReady: true, + writesBlocked: false, + }); + harness.api.setIndexedDbSnapshot( + buildSnapshotFromGraph( + createMeaningfulGraph("chat-sync-refresh-restore", "fresh-indexeddb-restore"), + { + chatId: "chat-sync-refresh-restore", + revision: 9, + }, + ), + ); + + const runtimeOptions = harness.api.buildBmeSyncRuntimeOptions(); + await runtimeOptions.onSyncApplied({ + chatId: "chat-sync-refresh-restore", + action: "restore-backup", + }); + + assert.equal( + harness.api.getCurrentGraph().nodes[0]?.fields?.title, + "事件-fresh-indexeddb-restore", + "restore-backup 后应刷新当前运行时图谱", + ); +} + { const harness = await createGraphPersistenceHarness({ chatId: "chat-sync-refresh-active", diff --git a/ui/panel-ena-sections.js b/ui/panel-ena-sections.js index fb2baae..323ce69 100644 --- a/ui/panel-ena-sections.js +++ b/ui/panel-ena-sections.js @@ -29,6 +29,7 @@ let undoState = null; let fieldChangeHandler = null; let autosaveInProgress = false; let externalGetSettings = null; +let pendingSavePatch = null; /* ── DOM helpers ────────────────────────────────────────────────────────── */ @@ -610,10 +611,20 @@ function resetPlannerSaveStatusIfReady() { /* ── Save flow ──────────────────────────────────────────────────────────── */ function scheduleSave() { + pendingSavePatch = collectPatch(); if (autoSaveTimer) clearTimeout(autoSaveTimer); autoSaveTimer = setTimeout(doSave, AUTOSAVE_DELAY_MS); } +function flushSave() { + if (autoSaveTimer) { + clearTimeout(autoSaveTimer); + autoSaveTimer = null; + } + pendingSavePatch = collectPatch(); + void doSave(); +} + async function doSave() { if (autosaveInProgress) return; const api = getPlannerApi(); @@ -624,9 +635,10 @@ async function doSave() { autosaveInProgress = true; setStatusChip('bme-planner-save-chip', '保存中…', 'loading'); try { - const patch = collectPatch(); + const patch = pendingSavePatch || collectPatch(); const res = await api.patchConfig(patch); if (res?.ok) { + pendingSavePatch = null; setStatusChip('bme-planner-save-chip', '已保存', 'success'); setTimeout(() => { if ($('bme-planner-save-chip')?.dataset?.tone === 'success') { @@ -665,6 +677,11 @@ function bindOnce(section) { toBool($('bme-planner-enabled').value, false) ? '已启用' : '未启用', toBool($('bme-planner-enabled').value, false) ? 'active' : 'idle', ); + flushSave(); + }); + + $('bme-planner-skip-plot')?.addEventListener('change', () => { + flushSave(); }); $('bme-planner-run-test')?.addEventListener('click', async () => { @@ -936,6 +953,8 @@ function bindOnce(section) { if (target.closest('.bme-planner-prompt-block')) return; if (target.id === 'bme-planner-test-input') return; if (target.id === 'bme-planner-llm-preset-select') return; + if (target.id === 'bme-planner-enabled') return; + if (target.id === 'bme-planner-skip-plot') return; if (!target.classList?.contains('bme-config-input')) return; syncPlannerLlmPresetSelect(); scheduleSave(); @@ -1017,6 +1036,7 @@ export function cleanupPlannerSections() { cfgCache = null; logsCache = []; fetchedModels = []; + pendingSavePatch = null; externalGetSettings = null; clearUndo(); }