// Extracted graph persistence IndexedDB I/O controllers. // Dependencies are supplied by index.js/test harnesses through runtime. function createGraphPersistenceStateProxy(runtime = {}) { return new Proxy({}, { get(_target, prop) { return runtime.getGraphPersistenceState?.()?.[prop]; }, set(_target, prop, value) { const state = runtime.getGraphPersistenceState?.(); if (state && typeof state === "object") { state[prop] = value; } else { runtime.setGraphPersistenceState?.({ [prop]: value }); } return true; }, has(_target, prop) { return prop in (runtime.getGraphPersistenceState?.() || {}); }, }); } function createNativeHydrateInstallPromiseRef(runtime = {}) { return { get value() { return typeof runtime.getNativeHydrateInstallPromise === "function" ? runtime.getNativeHydrateInstallPromise() : undefined; }, set value(nextValue) { if (typeof runtime.setNativeHydrateInstallPromise === "function") { runtime.setNativeHydrateInstallPromise(nextValue); } }, }; } function createNativePersistDeltaInstallPromiseRef(runtime = {}) { return { get value() { return typeof runtime.getNativePersistDeltaInstallPromise === "function" ? runtime.getNativePersistDeltaInstallPromise() : undefined; }, set value(nextValue) { if (typeof runtime.setNativePersistDeltaInstallPromise === "function") { runtime.setNativePersistDeltaInstallPromise(nextValue); } }, }; } function importNativeCore(runtime = {}) { return typeof runtime.importNativeCore === "function" ? runtime.importNativeCore() : import("../vendor/wasm/stbme_core.js"); } export async function loadGraphFromIndexedDbImpl(runtime, chatId, { source = "indexeddb-probe", attemptIndex = 0, allowOverride = false, applyEmptyState = false, } = {}, ) { const graphPersistenceState = createGraphPersistenceStateProxy(runtime); const currentGraph = runtime.getCurrentGraph?.() || null; const nativeHydrateInstallPromiseRef = createNativeHydrateInstallPromiseRef(runtime); const nativePersistDeltaInstallPromiseRef = createNativePersistDeltaInstallPromiseRef(runtime); const bmeIndexedDbLatestQueuedRevisionByChatId = runtime.bmeIndexedDbLatestQueuedRevisionByChatId; const bmeIndexedDbWriteInFlightByChatId = runtime.bmeIndexedDbWriteInFlightByChatId; const updateGraphPersistenceState = runtime.updateGraphPersistenceState || ((patch = {}) => runtime.setGraphPersistenceState?.({ ...(runtime.getGraphPersistenceState?.() || {}), ...(patch || {}) })); const AUTHORITY_GRAPH_STORE_KIND = runtime.AUTHORITY_GRAPH_STORE_KIND; const BME_INDEXEDDB_FALLBACK_LOAD_STATE_SET = runtime.BME_INDEXEDDB_FALLBACK_LOAD_STATE_SET; const GRAPH_LOAD_STATES = runtime.GRAPH_LOAD_STATES; const applyAcceptedPendingPersistState = runtime.applyAcceptedPendingPersistState; const applyGraphLoadState = runtime.applyGraphLoadState; const applyIndexedDbEmptyToRuntime = runtime.applyIndexedDbEmptyToRuntime; const applyIndexedDbSnapshotToRuntime = runtime.applyIndexedDbSnapshotToRuntime; const applyPersistDeltaToSnapshot = runtime.applyPersistDeltaToSnapshot; const applyShadowSnapshotToRuntime = runtime.applyShadowSnapshotToRuntime; const areChatIdsEquivalentForResolvedIdentity = runtime.areChatIdsEquivalentForResolvedIdentity; const buildBmeSyncRuntimeOptions = runtime.buildBmeSyncRuntimeOptions; const buildGraphLocalStoreSelectorKey = runtime.buildGraphLocalStoreSelectorKey; const buildGraphPersistResult = runtime.buildGraphPersistResult; const buildPersistDelta = runtime.buildPersistDelta; const buildPersistDeltaFromGraphDirtyState = runtime.buildPersistDeltaFromGraphDirtyState; const buildPersistObservabilitySummary = runtime.buildPersistObservabilitySummary; const buildPersistenceEnvironment = runtime.buildPersistenceEnvironment; const buildSnapshotFromGraph = runtime.buildSnapshotFromGraph; const cacheIndexedDbSnapshot = runtime.cacheIndexedDbSnapshot; const canPersistGraphToMetadataFallback = runtime.canPersistGraphToMetadataFallback; const clearPendingGraphPersistRetry = runtime.clearPendingGraphPersistRetry; const cloneGraphForPersistence = runtime.cloneGraphForPersistence; const cloneRuntimeDebugValue = runtime.cloneRuntimeDebugValue; const createShadowComparisonGraph = runtime.createShadowComparisonGraph; const detectIndexedDbSnapshotCommitMarkerMismatch = runtime.detectIndexedDbSnapshotCommitMarkerMismatch; const detectStaleIndexedDbSnapshotAgainstRuntime = runtime.detectStaleIndexedDbSnapshotAgainstRuntime; const ensureBmeChatManager = runtime.ensureBmeChatManager; const ensureCurrentGraphRuntimeState = runtime.ensureCurrentGraphRuntimeState; const evaluateNativeHydrateGate = runtime.evaluateNativeHydrateGate; const evaluatePersistNativeDeltaGate = runtime.evaluatePersistNativeDeltaGate; const getChatMetadataIntegrity = runtime.getChatMetadataIntegrity; const getContext = runtime.getContext; const getCurrentChatId = runtime.getCurrentChatId; const getGraphPersistedRevision = runtime.getGraphPersistedRevision; const getPreferredGraphLocalStorePresentationSync = runtime.getPreferredGraphLocalStorePresentationSync; const getRequestedGraphLocalStorageMode = runtime.getRequestedGraphLocalStorageMode; const getSettings = runtime.getSettings; const hasMeaningfulRuntimeGraphForChat = runtime.hasMeaningfulRuntimeGraphForChat; const isAuthorityGraphStorePresentation = runtime.isAuthorityGraphStorePresentation; const isGraphLocalStorageModeOpfs = runtime.isGraphLocalStorageModeOpfs; const isIndexedDbSnapshotMeaningful = runtime.isIndexedDbSnapshotMeaningful; const isRestoreLockActive = runtime.isRestoreLockActive; const maybeCaptureGraphShadowSnapshot = runtime.maybeCaptureGraphShadowSnapshot; const maybeClearAcceptedPendingPersistState = runtime.maybeClearAcceptedPendingPersistState; const maybeImportLegacyIndexedDbSnapshotToLocalStore = runtime.maybeImportLegacyIndexedDbSnapshotToLocalStore; const maybeImportLegacyOpfsSnapshotToLocalStore = runtime.maybeImportLegacyOpfsSnapshotToLocalStore; const maybeMigrateLegacyGraphToIndexedDb = runtime.maybeMigrateLegacyGraphToIndexedDb; const maybeRecoverIndexedDbGraphFromStableIdentity = runtime.maybeRecoverIndexedDbGraphFromStableIdentity; const maybeResolveOrphanAcceptedCommitMarker = runtime.maybeResolveOrphanAcceptedCommitMarker; const maybeResumePendingAutoExtraction = runtime.maybeResumePendingAutoExtraction; const normalizeChatIdCandidate = runtime.normalizeChatIdCandidate; const normalizeGraphRuntimeState = runtime.normalizeGraphRuntimeState; const normalizeIndexedDbRevision = runtime.normalizeIndexedDbRevision; const normalizeLoadDiagnosticsMs = runtime.normalizeLoadDiagnosticsMs; const normalizePersistDeltaDiagnosticsMs = runtime.normalizePersistDeltaDiagnosticsMs; const persistGraphToChatMetadata = runtime.persistGraphToChatMetadata; const persistGraphToConfiguredDurableTier = runtime.persistGraphToConfiguredDurableTier; const pruneGraphPersistDirtyState = runtime.pruneGraphPersistDirtyState; const queueGraphPersist = runtime.queueGraphPersist; const queueRuntimeGraphLocalStoreRepair = runtime.queueRuntimeGraphLocalStoreRepair; const readCachedIndexedDbSnapshot = runtime.readCachedIndexedDbSnapshot; const readLoadDiagnosticsNow = runtime.readLoadDiagnosticsNow; const readLocalStoreDiagnosticsSync = runtime.readLocalStoreDiagnosticsSync; const readPersistDeltaDiagnosticsNow = runtime.readPersistDeltaDiagnosticsNow; const recordLocalPersistEarlyFailure = runtime.recordLocalPersistEarlyFailure; const recordPersistMismatchDiagnostic = runtime.recordPersistMismatchDiagnostic; const refreshCurrentChatLocalStoreBinding = runtime.refreshCurrentChatLocalStoreBinding; const rememberResolvedGraphIdentityAlias = runtime.rememberResolvedGraphIdentityAlias; const resolveCompatibleGraphShadowSnapshot = runtime.resolveCompatibleGraphShadowSnapshot; const resolveCurrentChatIdentity = runtime.resolveCurrentChatIdentity; const resolveDbGraphStorePresentation = runtime.resolveDbGraphStorePresentation; const resolveLocalStoreTierFromPresentation = runtime.resolveLocalStoreTierFromPresentation; const resolvePendingPersistGraphSource = runtime.resolvePendingPersistGraphSource; const resolvePendingPersistLastProcessedAssistantFloor = runtime.resolvePendingPersistLastProcessedAssistantFloor; const resolvePersistRevisionFloor = runtime.resolvePersistRevisionFloor; const resolveSnapshotGraphStorePresentation = runtime.resolveSnapshotGraphStorePresentation; const schedulePendingGraphPersistRetry = runtime.schedulePendingGraphPersistRetry; const scheduleUpload = runtime.scheduleUpload; const shouldPreferShadowSnapshotOverOfficial = runtime.shouldPreferShadowSnapshotOverOfficial; const stampGraphPersistenceMeta = runtime.stampGraphPersistenceMeta; const syncCommitMarkerToPersistenceState = runtime.syncCommitMarkerToPersistenceState; const updateLoadDiagnostics = runtime.updateLoadDiagnostics; const updatePersistDeltaDiagnostics = runtime.updatePersistDeltaDiagnostics; const console = runtime.console || globalThis.console; const normalizedChatId = normalizeChatIdCandidate(chatId); const commitMarker = syncCommitMarkerToPersistenceState(getContext()); const loadStartedAt = readLoadDiagnosticsNow(); const recordLoadDiagnostics = (patch = {}) => updateLoadDiagnostics({ stage: "load-indexeddb", source: String(source || "indexeddb-probe"), chatId: normalizedChatId || "", attemptIndex: Number.isFinite(Number(attemptIndex)) ? Math.max(0, Math.floor(Number(attemptIndex))) : 0, ...cloneRuntimeDebugValue(patch, {}), totalMs: normalizeLoadDiagnosticsMs(readLoadDiagnosticsNow() - loadStartedAt), }); let exportSnapshotMs = 0; let exportProbeMs = 0; let preApplyMs = 0; let exportSnapshotSource = ""; const currentSettings = getSettings(); if (!normalizedChatId) { const result = { success: false, loaded: false, reason: "indexeddb-missing-chat-id", chatId: "", attemptIndex, }; recordLoadDiagnostics({ success: false, loaded: false, reason: result.reason, }); return result; } let localStore = getPreferredGraphLocalStorePresentationSync(); try { const manager = ensureBmeChatManager(); if (!manager) { const result = { success: false, loaded: false, reason: "indexeddb-manager-unavailable", chatId: normalizedChatId, attemptIndex, }; recordLoadDiagnostics({ success: false, loaded: false, reason: result.reason, storagePrimary: localStore.storagePrimary, storageMode: localStore.storageMode, }); return result; } const db = await manager.getCurrentDb(normalizedChatId); localStore = resolveDbGraphStorePresentation(db); const identityRecoveryResult = await maybeRecoverIndexedDbGraphFromStableIdentity( normalizedChatId, getContext(), { source, db, }, ); if (identityRecoveryResult?.migrated) { const recoveredStore = resolveSnapshotGraphStorePresentation( identityRecoveryResult?.snapshot, localStore, ); const recoveredAuthorityStore = isAuthorityGraphStorePresentation(recoveredStore); const recoveredRevision = normalizeIndexedDbRevision( identityRecoveryResult?.snapshot?.meta?.revision, ); updateGraphPersistenceState({ storagePrimary: recoveredStore.storagePrimary, storageMode: recoveredStore.storageMode, resolvedLocalStore: buildGraphLocalStoreSelectorKey(recoveredStore), localStoreFormatVersion: recoveredStore.storagePrimary === "opfs" ? 2 : 1, localStoreMigrationState: "completed", authorityMigrationState: recoveredAuthorityStore ? "completed" : graphPersistenceState.authorityMigrationState, authorityMigrationSource: recoveredAuthorityStore ? String(identityRecoveryResult?.source || "identity-recovery") : graphPersistenceState.authorityMigrationSource, authorityMigrationRevision: recoveredAuthorityStore ? recoveredRevision : graphPersistenceState.authorityMigrationRevision, authorityMigrationLastError: recoveredAuthorityStore ? "" : graphPersistenceState.authorityMigrationLastError, lastAuthorityMigrationResult: recoveredAuthorityStore ? cloneRuntimeDebugValue(identityRecoveryResult, null) : graphPersistenceState.lastAuthorityMigrationResult, indexedDbRevision: recoveredRevision, indexedDbLastError: "", lastSyncError: "", dualWriteLastResult: { action: "identity-recovery", source: String(identityRecoveryResult?.source || recoveredStore.reasonPrefix), success: true, chatId: normalizedChatId, legacyChatId: String(identityRecoveryResult?.legacyChatId || ""), revision: recoveredRevision, reason: String( identityRecoveryResult?.reason || "identity-recovery", ), at: Date.now(), syncResult: cloneRuntimeDebugValue( identityRecoveryResult?.syncResult, null, ), }, }); } const opfsMigrationResult = identityRecoveryResult?.migrated ? { migrated: false, reason: "identity-recovery-already-applied", chatId: normalizedChatId, } : await maybeImportLegacyOpfsSnapshotToLocalStore( normalizedChatId, db, { source, }, ); const localStoreMigrationResult = identityRecoveryResult?.migrated || opfsMigrationResult?.migrated ? { migrated: false, reason: opfsMigrationResult?.migrated ? "opfs-migration-already-applied" : "identity-recovery-already-applied", chatId: normalizedChatId, } : await maybeImportLegacyIndexedDbSnapshotToLocalStore( normalizedChatId, db, { source, }, ); const migrationResult = identityRecoveryResult?.migrated || opfsMigrationResult?.migrated || localStoreMigrationResult?.migrated || localStoreMigrationResult?.reason === "migration-local-store-failed" ? localStoreMigrationResult : await maybeMigrateLegacyGraphToIndexedDb( normalizedChatId, getContext(), { source, db, }, ); if (migrationResult?.migrated) { const migratedStore = resolveSnapshotGraphStorePresentation( migrationResult?.snapshot, localStore, ); const migratedAuthorityStore = isAuthorityGraphStorePresentation(migratedStore); const migratedRevision = normalizeIndexedDbRevision( migrationResult?.snapshot?.meta?.revision || migrationResult?.migrationResult?.revision, ); updateGraphPersistenceState({ storagePrimary: migratedStore.storagePrimary, storageMode: migratedStore.storageMode, resolvedLocalStore: buildGraphLocalStoreSelectorKey(migratedStore), localStoreFormatVersion: migratedStore.storagePrimary === "opfs" ? 2 : 1, localStoreMigrationState: "completed", authorityMigrationState: migratedAuthorityStore ? "completed" : graphPersistenceState.authorityMigrationState, authorityMigrationSource: migratedAuthorityStore ? String(migrationResult?.source || migrationResult?.reason || "") : graphPersistenceState.authorityMigrationSource, authorityMigrationRevision: migratedAuthorityStore ? migratedRevision : graphPersistenceState.authorityMigrationRevision, authorityMigrationLastError: migratedAuthorityStore ? "" : graphPersistenceState.authorityMigrationLastError, lastAuthorityMigrationResult: migratedAuthorityStore ? cloneRuntimeDebugValue(migrationResult, null) : graphPersistenceState.lastAuthorityMigrationResult, indexedDbRevision: migratedRevision, indexedDbLastError: "", lastSyncError: "", dualWriteLastResult: { action: "migration", source: String(migrationResult?.source || "chat_metadata"), success: true, chatId: normalizedChatId, revision: migratedRevision, reason: migrationResult?.reason || "migration-completed", at: Date.now(), syncResult: cloneRuntimeDebugValue(migrationResult?.syncResult, null), }, }); } else if ( migrationResult?.reason === "migration-failed" || migrationResult?.reason === "migration-local-store-failed" ) { updateGraphPersistenceState({ indexedDbLastError: String( migrationResult?.error || "migration-failed", ), localStoreMigrationState: "failed", authorityMigrationState: localStore.storagePrimary === AUTHORITY_GRAPH_STORE_KIND ? "failed" : graphPersistenceState.authorityMigrationState, authorityMigrationLastError: localStore.storagePrimary === AUTHORITY_GRAPH_STORE_KIND ? String(migrationResult?.error || migrationResult?.reason || "migration-failed") : graphPersistenceState.authorityMigrationLastError, lastAuthorityMigrationResult: localStore.storagePrimary === AUTHORITY_GRAPH_STORE_KIND ? cloneRuntimeDebugValue(migrationResult, null) : graphPersistenceState.lastAuthorityMigrationResult, dualWriteLastResult: { action: "migration", source: "chat_metadata", success: false, error: String(migrationResult?.error || "migration-failed"), at: Date.now(), }, }); } let snapshot = null; let inspectionSnapshot = null; if (identityRecoveryResult?.snapshot) { snapshot = identityRecoveryResult.snapshot; inspectionSnapshot = snapshot; exportSnapshotSource = "identity-recovery"; } else if (localStoreMigrationResult?.snapshot) { snapshot = localStoreMigrationResult.snapshot; inspectionSnapshot = snapshot; exportSnapshotSource = "local-store-migration"; } else if (migrationResult?.snapshot) { snapshot = migrationResult.snapshot; inspectionSnapshot = snapshot; exportSnapshotSource = "legacy-migration"; } else { if (typeof db.exportSnapshotProbe === "function") { const probeStartedAt = readLoadDiagnosticsNow(); inspectionSnapshot = await db.exportSnapshotProbe({ includeTombstones: false }); exportProbeMs = readLoadDiagnosticsNow() - probeStartedAt; exportSnapshotSource = "indexeddb-probe"; } if (!inspectionSnapshot) { const exportStartedAt = readLoadDiagnosticsNow(); snapshot = await db.exportSnapshot({ includeTombstones: false }); exportSnapshotMs = readLoadDiagnosticsNow() - exportStartedAt; inspectionSnapshot = snapshot; exportSnapshotSource = "indexeddb-export"; } } const shadowSnapshot = resolveCompatibleGraphShadowSnapshot( resolveCurrentChatIdentity(getContext()), ); const snapshotStore = resolveSnapshotGraphStorePresentation( inspectionSnapshot || snapshot, localStore, ); const commitMarkerMismatch = detectIndexedDbSnapshotCommitMarkerMismatch( inspectionSnapshot, commitMarker, ); let commitMarkerDiagnostic = null; if (!isIndexedDbSnapshotMeaningful(inspectionSnapshot)) { if (commitMarkerMismatch.mismatched) { commitMarkerDiagnostic = recordPersistMismatchDiagnostic( commitMarkerMismatch, { source: `${source}:indexeddb-empty`, }, ); if ( shadowSnapshot && Number(shadowSnapshot.revision || 0) >= Number(commitMarkerMismatch.markerRevision || 0) ) { const shadowRestoreResult = applyShadowSnapshotToRuntime( normalizedChatId, shadowSnapshot, { source: `${source}:shadow-indexeddb-empty`, attemptIndex, }, ); if (shadowRestoreResult?.loaded) { updateGraphPersistenceState({ persistMismatchReason: commitMarkerDiagnostic.reason, }); return shadowRestoreResult; } } } if (shadowSnapshot) { const shadowRestoreResult = applyShadowSnapshotToRuntime( normalizedChatId, shadowSnapshot, { source: `${source}:shadow-indexeddb-empty`, attemptIndex, }, ); if (shadowRestoreResult?.loaded) { return shadowRestoreResult; } } if (commitMarkerDiagnostic?.reason) { const orphanMarkerResolution = await maybeResolveOrphanAcceptedCommitMarker(normalizedChatId, { source, attemptIndex, commitMarker, migrationResult, shadowSnapshot, applyEmptyState, }); if (orphanMarkerResolution?.result) { if ( !orphanMarkerResolution.orphanCleared && orphanMarkerResolution.result?.loaded ) { updateGraphPersistenceState({ persistMismatchReason: commitMarkerDiagnostic.reason, }); } return orphanMarkerResolution.result; } } const runtimeRepair = queueRuntimeGraphLocalStoreRepair(normalizedChatId, { source: `${source}:empty-local-store`, scheduleCloudUpload: false, }); if (runtimeRepair.queued) { return { success: true, loaded: false, repairQueued: true, loadState: GRAPH_LOAD_STATES.LOADING, reason: `${snapshotStore.reasonPrefix}-repair-queued`, chatId: normalizedChatId, attemptIndex, revision: Number(runtimeRepair.revision || 0), }; } if ( applyEmptyState && !commitMarkerDiagnostic?.reason && getCurrentChatId() === normalizedChatId ) { return applyIndexedDbEmptyToRuntime(normalizedChatId, { source, attemptIndex, }); } return { success: false, loaded: false, reason: commitMarkerDiagnostic?.reason || `${snapshotStore.reasonPrefix}-empty`, chatId: normalizedChatId, attemptIndex, }; } const snapshotRevision = normalizeIndexedDbRevision( inspectionSnapshot?.meta?.revision, ); const snapshotIntegrity = String(inspectionSnapshot?.meta?.integrity || "").trim(); const shadowDecision = shouldPreferShadowSnapshotOverOfficial( createShadowComparisonGraph({ chatId: normalizedChatId, revision: snapshotRevision, integrity: snapshotIntegrity, }), shadowSnapshot, ); if (shadowSnapshot && shadowDecision?.reason) { updateGraphPersistenceState({ dualWriteLastResult: { action: "shadow-compare", source: `${source}:indexeddb-shadow-compare`, success: Boolean(shadowDecision.prefer), reason: shadowDecision.reason, resultCode: String(shadowDecision.resultCode || ""), shadowRevision: Number(shadowSnapshot.revision || 0), officialRevision: snapshotRevision, at: Date.now(), }, }); } if (shadowSnapshot && shadowDecision?.prefer) { return applyShadowSnapshotToRuntime( normalizedChatId, shadowSnapshot, { source: `${source}:shadow-newer-than-indexeddb`, attemptIndex, }, ); } if (commitMarkerMismatch.mismatched) { commitMarkerDiagnostic = recordPersistMismatchDiagnostic( { ...commitMarkerMismatch, marker: commitMarkerMismatch.marker || commitMarker, }, { source: `${source}:indexeddb-commit-marker`, }, ); if ( shadowSnapshot && Number(shadowSnapshot.revision || 0) >= Number(commitMarkerMismatch.markerRevision || 0) ) { const shadowResult = applyShadowSnapshotToRuntime( normalizedChatId, shadowSnapshot, { source: `${source}:shadow-beats-commit-marker`, attemptIndex, }, ); if (shadowResult?.loaded && commitMarkerDiagnostic?.reason) { updateGraphPersistenceState({ persistMismatchReason: commitMarkerDiagnostic.reason, }); } return shadowResult; } } const shouldAllowOverride = allowOverride || BME_INDEXEDDB_FALLBACK_LOAD_STATE_SET.has( graphPersistenceState.loadState, ) || graphPersistenceState.storagePrimary === snapshotStore.storagePrimary || snapshotRevision >= normalizeIndexedDbRevision(graphPersistenceState.revision); if (!shouldAllowOverride) { return { success: false, loaded: false, reason: `${snapshotStore.reasonPrefix}-stale`, chatId: normalizedChatId, attemptIndex, revision: snapshotRevision, }; } if (getCurrentChatId() !== normalizedChatId) { return { success: false, loaded: false, reason: `${snapshotStore.reasonPrefix}-chat-switched`, chatId: normalizedChatId, attemptIndex, revision: snapshotRevision, }; } const staleDecision = detectStaleIndexedDbSnapshotAgainstRuntime( normalizedChatId, inspectionSnapshot, ); if (staleDecision.stale) { const result = { success: false, loaded: false, reason: `${snapshotStore.reasonPrefix}-stale-runtime`, chatId: normalizedChatId, attemptIndex, revision: snapshotRevision, staleDetail: cloneRuntimeDebugValue(staleDecision, null), }; updateGraphPersistenceState({ storagePrimary: snapshotStore.storagePrimary, storageMode: snapshotStore.storageMode, indexedDbLastError: "", dualWriteLastResult: { action: "load", source: String(source || snapshotStore.reasonPrefix), success: false, rejected: true, reason: result.reason, revision: snapshotRevision, staleDetail: cloneRuntimeDebugValue(staleDecision, null), at: Date.now(), }, }); recordLoadDiagnostics({ success: false, loaded: false, reason: result.reason, revision: snapshotRevision, storagePrimary: snapshotStore.storagePrimary, storageMode: snapshotStore.storageMode, exportSnapshotSource: exportSnapshotSource || "snapshot-probe", exportProbeMs: normalizeLoadDiagnosticsMs(exportProbeMs), exportSnapshotMs: normalizeLoadDiagnosticsMs(exportSnapshotMs), preApplyMs: normalizeLoadDiagnosticsMs(readLoadDiagnosticsNow() - loadStartedAt), preApplyOtherMs: normalizeLoadDiagnosticsMs( Math.max( 0, readLoadDiagnosticsNow() - loadStartedAt - exportSnapshotMs - exportProbeMs, ), ), staleDetail: cloneRuntimeDebugValue(staleDecision, null), }); return result; } if (!snapshot) { const exportStartedAt = readLoadDiagnosticsNow(); snapshot = await db.exportSnapshot({ includeTombstones: false }); exportSnapshotMs += readLoadDiagnosticsNow() - exportStartedAt; exportSnapshotSource = exportSnapshotSource === "indexeddb-probe" ? "indexeddb-probe+indexeddb-export" : exportSnapshotSource || "indexeddb-export"; } cacheIndexedDbSnapshot(normalizedChatId, snapshot); const nativeHydrateRequested = currentSettings.loadUseNativeHydrate === true; const nativeHydrateForceDisabled = currentSettings.graphNativeForceDisable === true; const nativeHydrateGate = evaluateNativeHydrateGate(snapshot, currentSettings); const shouldUseNativeHydrate = nativeHydrateRequested && nativeHydrateForceDisabled !== true && nativeHydrateGate.allowed; let nativeHydrateModuleStatus = null; let nativeHydratePreloadStatus = nativeHydrateRequested ? nativeHydrateForceDisabled ? "force-disabled" : nativeHydrateGate.allowed ? "pending" : "gated-out" : "not-requested"; let nativeHydratePreloadError = ""; let nativeHydratePreloadMs = 0; if (shouldUseNativeHydrate) { const preloadStartedAt = readLoadDiagnosticsNow(); try { if (!nativeHydrateInstallPromiseRef.value) { nativeHydrateInstallPromiseRef.value = importNativeCore(runtime) .then((module) => module?.installNativeHydrateHook?.()) .catch((error) => { nativeHydrateInstallPromiseRef.value = null; throw error; }); } nativeHydrateModuleStatus = await nativeHydrateInstallPromiseRef.value; nativeHydratePreloadStatus = nativeHydrateModuleStatus?.loaded ? "loaded" : "not-loaded"; nativeHydratePreloadMs = readLoadDiagnosticsNow() - preloadStartedAt; } catch (error) { nativeHydratePreloadStatus = "failed"; nativeHydratePreloadMs = readLoadDiagnosticsNow() - preloadStartedAt; nativeHydratePreloadError = error?.message || String(error); if (currentSettings.nativeEngineFailOpen !== false) { console.warn( "[ST-BME] native hydrate preload failed, fallback to JS hydrate:", error, ); } else { throw error; } } } preApplyMs = readLoadDiagnosticsNow() - loadStartedAt; const applyInvokeStartedAt = readLoadDiagnosticsNow(); const loadResult = applyIndexedDbSnapshotToRuntime(normalizedChatId, snapshot, { source, attemptIndex, storagePrimary: snapshotStore.storagePrimary, storageMode: snapshotStore.storageMode, statusLabel: snapshotStore.statusLabel, reasonPrefix: snapshotStore.reasonPrefix, currentSettings, nativeHydrateRequested, nativeHydrateForceDisabled, nativeHydrateGate, nativeHydratePreloadStatus, nativeHydratePreloadMs, nativeHydratePreloadError, nativeHydrateModuleStatus, }); const applyInvokeMs = readLoadDiagnosticsNow() - applyInvokeStartedAt; const totalLoadMs = readLoadDiagnosticsNow() - loadStartedAt; const loadAccountedMs = preApplyMs + applyInvokeMs; if (commitMarkerDiagnostic?.reason && loadResult?.loaded) { updateGraphPersistenceState({ persistMismatchReason: commitMarkerDiagnostic.reason, }); } recordLoadDiagnostics({ success: loadResult?.success === true, loaded: loadResult?.loaded === true, reason: String(loadResult?.reason || ""), revision: Number.isFinite(Number(loadResult?.revision)) ? Number(loadResult.revision) : snapshotRevision, storagePrimary: snapshotStore.storagePrimary, storageMode: snapshotStore.storageMode, commitMarkerMismatched: commitMarkerMismatch.mismatched === true, exportSnapshotSource: exportSnapshotSource || "snapshot-prepared", exportProbeMs: normalizeLoadDiagnosticsMs(exportProbeMs), exportSnapshotMs: normalizeLoadDiagnosticsMs(exportSnapshotMs), preApplyMs: normalizeLoadDiagnosticsMs(preApplyMs), preApplyOtherMs: normalizeLoadDiagnosticsMs( Math.max(0, preApplyMs - exportSnapshotMs - exportProbeMs), ), hydrateNativeRequested: loadResult?.nativeHydrateRequested === true, hydrateNativeForceDisabled: loadResult?.nativeHydrateForceDisabled === true, hydrateNativeGateAllowed: loadResult?.nativeHydrateGate?.allowed === true, hydrateNativeGateReasons: cloneRuntimeDebugValue( loadResult?.nativeHydrateGate?.reasons, [], ), hydrateNativePreloadStatus: String( loadResult?.nativeHydratePreloadStatus || nativeHydratePreloadStatus || "", ), hydrateNativePreloadMs: normalizeLoadDiagnosticsMs( loadResult?.nativeHydratePreloadMs, ), hydrateNativePreloadError: String( loadResult?.nativeHydratePreloadError || "", ), hydrateNativeModuleLoaded: Boolean( loadResult?.nativeHydrateModuleStatus?.loaded, ), hydrateNativeModuleSource: String( loadResult?.nativeHydrateModuleStatus?.source || "", ), hydrateNativeModuleError: String( loadResult?.nativeHydrateModuleStatus?.error || "", ), hydrateNativeUsed: loadResult?.hydrateDiagnostics?.nativeUsed === true, hydrateNativeStatus: String( loadResult?.hydrateDiagnostics?.nativeStatus || "", ), hydrateNativeError: String(loadResult?.hydrateDiagnostics?.nativeError || ""), hydrateNativeRecordsMs: normalizeLoadDiagnosticsMs( loadResult?.hydrateDiagnostics?.nativeRecordsMs, ), applyInvokeMs: normalizeLoadDiagnosticsMs(applyInvokeMs), untrackedMs: normalizeLoadDiagnosticsMs( Math.max(0, totalLoadMs - loadAccountedMs), ), }); return loadResult; } catch (error) { console.warn(`[ST-BME] ${localStore.statusLabel} 读取失败,回退 metadata:`, error); updateGraphPersistenceState({ storagePrimary: localStore.storagePrimary, storageMode: localStore.storageMode, indexedDbLastError: error?.message || String(error), dualWriteLastResult: { action: "load", source: String(source || localStore.reasonPrefix), success: false, error: error?.message || String(error), at: Date.now(), }, }); const result = { success: false, loaded: false, reason: `${localStore.reasonPrefix}-read-failed`, chatId: normalizedChatId, attemptIndex, error, }; recordLoadDiagnostics({ success: false, loaded: false, reason: result.reason, storagePrimary: localStore.storagePrimary, storageMode: localStore.storageMode, error: error?.message || String(error), exportSnapshotSource: exportSnapshotSource || "unknown", exportProbeMs: normalizeLoadDiagnosticsMs(exportProbeMs), exportSnapshotMs: normalizeLoadDiagnosticsMs(exportSnapshotMs), preApplyMs: normalizeLoadDiagnosticsMs( preApplyMs || (readLoadDiagnosticsNow() - loadStartedAt), ), preApplyOtherMs: normalizeLoadDiagnosticsMs( Math.max( 0, (preApplyMs || (readLoadDiagnosticsNow() - loadStartedAt)) - exportSnapshotMs - exportProbeMs, ), ), }); return result; } } export function maybeFlushQueuedGraphPersistImpl(runtime, reason = "queued-graph-persist") { const graphPersistenceState = createGraphPersistenceStateProxy(runtime); const currentGraph = runtime.getCurrentGraph?.() || null; const nativeHydrateInstallPromiseRef = createNativeHydrateInstallPromiseRef(runtime); const nativePersistDeltaInstallPromiseRef = createNativePersistDeltaInstallPromiseRef(runtime); const bmeIndexedDbLatestQueuedRevisionByChatId = runtime.bmeIndexedDbLatestQueuedRevisionByChatId; const bmeIndexedDbWriteInFlightByChatId = runtime.bmeIndexedDbWriteInFlightByChatId; const updateGraphPersistenceState = runtime.updateGraphPersistenceState || ((patch = {}) => runtime.setGraphPersistenceState?.({ ...(runtime.getGraphPersistenceState?.() || {}), ...(patch || {}) })); const AUTHORITY_GRAPH_STORE_KIND = runtime.AUTHORITY_GRAPH_STORE_KIND; const BME_INDEXEDDB_FALLBACK_LOAD_STATE_SET = runtime.BME_INDEXEDDB_FALLBACK_LOAD_STATE_SET; const GRAPH_LOAD_STATES = runtime.GRAPH_LOAD_STATES; const applyAcceptedPendingPersistState = runtime.applyAcceptedPendingPersistState; const applyGraphLoadState = runtime.applyGraphLoadState; const applyIndexedDbEmptyToRuntime = runtime.applyIndexedDbEmptyToRuntime; const applyIndexedDbSnapshotToRuntime = runtime.applyIndexedDbSnapshotToRuntime; const applyPersistDeltaToSnapshot = runtime.applyPersistDeltaToSnapshot; const applyShadowSnapshotToRuntime = runtime.applyShadowSnapshotToRuntime; const areChatIdsEquivalentForResolvedIdentity = runtime.areChatIdsEquivalentForResolvedIdentity; const buildBmeSyncRuntimeOptions = runtime.buildBmeSyncRuntimeOptions; const buildGraphLocalStoreSelectorKey = runtime.buildGraphLocalStoreSelectorKey; const buildGraphPersistResult = runtime.buildGraphPersistResult; const buildPersistDelta = runtime.buildPersistDelta; const buildPersistDeltaFromGraphDirtyState = runtime.buildPersistDeltaFromGraphDirtyState; const buildPersistObservabilitySummary = runtime.buildPersistObservabilitySummary; const buildPersistenceEnvironment = runtime.buildPersistenceEnvironment; const buildSnapshotFromGraph = runtime.buildSnapshotFromGraph; const cacheIndexedDbSnapshot = runtime.cacheIndexedDbSnapshot; const canPersistGraphToMetadataFallback = runtime.canPersistGraphToMetadataFallback; const clearPendingGraphPersistRetry = runtime.clearPendingGraphPersistRetry; const cloneGraphForPersistence = runtime.cloneGraphForPersistence; const cloneRuntimeDebugValue = runtime.cloneRuntimeDebugValue; const createShadowComparisonGraph = runtime.createShadowComparisonGraph; const detectIndexedDbSnapshotCommitMarkerMismatch = runtime.detectIndexedDbSnapshotCommitMarkerMismatch; const detectStaleIndexedDbSnapshotAgainstRuntime = runtime.detectStaleIndexedDbSnapshotAgainstRuntime; const ensureBmeChatManager = runtime.ensureBmeChatManager; const ensureCurrentGraphRuntimeState = runtime.ensureCurrentGraphRuntimeState; const evaluateNativeHydrateGate = runtime.evaluateNativeHydrateGate; const evaluatePersistNativeDeltaGate = runtime.evaluatePersistNativeDeltaGate; const getChatMetadataIntegrity = runtime.getChatMetadataIntegrity; const getContext = runtime.getContext; const getCurrentChatId = runtime.getCurrentChatId; const getGraphPersistedRevision = runtime.getGraphPersistedRevision; const getPreferredGraphLocalStorePresentationSync = runtime.getPreferredGraphLocalStorePresentationSync; const getRequestedGraphLocalStorageMode = runtime.getRequestedGraphLocalStorageMode; const getSettings = runtime.getSettings; const hasMeaningfulRuntimeGraphForChat = runtime.hasMeaningfulRuntimeGraphForChat; const isAuthorityGraphStorePresentation = runtime.isAuthorityGraphStorePresentation; const isGraphLocalStorageModeOpfs = runtime.isGraphLocalStorageModeOpfs; const isIndexedDbSnapshotMeaningful = runtime.isIndexedDbSnapshotMeaningful; const isRestoreLockActive = runtime.isRestoreLockActive; const maybeCaptureGraphShadowSnapshot = runtime.maybeCaptureGraphShadowSnapshot; const maybeClearAcceptedPendingPersistState = runtime.maybeClearAcceptedPendingPersistState; const maybeImportLegacyIndexedDbSnapshotToLocalStore = runtime.maybeImportLegacyIndexedDbSnapshotToLocalStore; const maybeImportLegacyOpfsSnapshotToLocalStore = runtime.maybeImportLegacyOpfsSnapshotToLocalStore; const maybeMigrateLegacyGraphToIndexedDb = runtime.maybeMigrateLegacyGraphToIndexedDb; const maybeRecoverIndexedDbGraphFromStableIdentity = runtime.maybeRecoverIndexedDbGraphFromStableIdentity; const maybeResolveOrphanAcceptedCommitMarker = runtime.maybeResolveOrphanAcceptedCommitMarker; const maybeResumePendingAutoExtraction = runtime.maybeResumePendingAutoExtraction; const normalizeChatIdCandidate = runtime.normalizeChatIdCandidate; const normalizeGraphRuntimeState = runtime.normalizeGraphRuntimeState; const normalizeIndexedDbRevision = runtime.normalizeIndexedDbRevision; const normalizeLoadDiagnosticsMs = runtime.normalizeLoadDiagnosticsMs; const normalizePersistDeltaDiagnosticsMs = runtime.normalizePersistDeltaDiagnosticsMs; const persistGraphToChatMetadata = runtime.persistGraphToChatMetadata; const persistGraphToConfiguredDurableTier = runtime.persistGraphToConfiguredDurableTier; const pruneGraphPersistDirtyState = runtime.pruneGraphPersistDirtyState; const queueGraphPersist = runtime.queueGraphPersist; const queueRuntimeGraphLocalStoreRepair = runtime.queueRuntimeGraphLocalStoreRepair; const readCachedIndexedDbSnapshot = runtime.readCachedIndexedDbSnapshot; const readLoadDiagnosticsNow = runtime.readLoadDiagnosticsNow; const readLocalStoreDiagnosticsSync = runtime.readLocalStoreDiagnosticsSync; const readPersistDeltaDiagnosticsNow = runtime.readPersistDeltaDiagnosticsNow; const recordLocalPersistEarlyFailure = runtime.recordLocalPersistEarlyFailure; const recordPersistMismatchDiagnostic = runtime.recordPersistMismatchDiagnostic; const refreshCurrentChatLocalStoreBinding = runtime.refreshCurrentChatLocalStoreBinding; const rememberResolvedGraphIdentityAlias = runtime.rememberResolvedGraphIdentityAlias; const resolveCompatibleGraphShadowSnapshot = runtime.resolveCompatibleGraphShadowSnapshot; const resolveCurrentChatIdentity = runtime.resolveCurrentChatIdentity; const resolveDbGraphStorePresentation = runtime.resolveDbGraphStorePresentation; const resolveLocalStoreTierFromPresentation = runtime.resolveLocalStoreTierFromPresentation; const resolvePendingPersistGraphSource = runtime.resolvePendingPersistGraphSource; const resolvePendingPersistLastProcessedAssistantFloor = runtime.resolvePendingPersistLastProcessedAssistantFloor; const resolvePersistRevisionFloor = runtime.resolvePersistRevisionFloor; const resolveSnapshotGraphStorePresentation = runtime.resolveSnapshotGraphStorePresentation; const schedulePendingGraphPersistRetry = runtime.schedulePendingGraphPersistRetry; const scheduleUpload = runtime.scheduleUpload; const shouldPreferShadowSnapshotOverOfficial = runtime.shouldPreferShadowSnapshotOverOfficial; const stampGraphPersistenceMeta = runtime.stampGraphPersistenceMeta; const syncCommitMarkerToPersistenceState = runtime.syncCommitMarkerToPersistenceState; const updateLoadDiagnostics = runtime.updateLoadDiagnostics; const updatePersistDeltaDiagnostics = runtime.updatePersistDeltaDiagnostics; const console = runtime.console || globalThis.console; const context = getContext(); if (!currentGraph || !canPersistGraphToMetadataFallback(context)) { return buildGraphPersistResult({ queued: graphPersistenceState.pendingPersist, blocked: !canPersistGraphToMetadataFallback(context), reason: canPersistGraphToMetadataFallback(context) ? "missing-current-graph" : "write-protected", }); } if ( !graphPersistenceState.pendingPersist && graphPersistenceState.queuedPersistRevision <= graphPersistenceState.lastPersistedRevision ) { return buildGraphPersistResult({ saved: false, reason: "no-queued-persist", }); } const activeChatId = getCurrentChatId(); const queuedChatId = String(graphPersistenceState.queuedPersistChatId || ""); if (queuedChatId && activeChatId && queuedChatId !== activeChatId) { return buildGraphPersistResult({ saved: false, queued: graphPersistenceState.pendingPersist, blocked: true, reason: "queued-chat-mismatch", revision: graphPersistenceState.queuedPersistRevision, saveMode: graphPersistenceState.queuedPersistMode, }); } const targetRevision = Math.max( graphPersistenceState.revision || 0, graphPersistenceState.queuedPersistRevision || 0, ); if (targetRevision > (graphPersistenceState.revision || 0)) { updateGraphPersistenceState({ revision: targetRevision, }); } return persistGraphToChatMetadata(context, { reason, revision: targetRevision, immediate: graphPersistenceState.queuedPersistMode !== "debounced", }); } export async function retryPendingGraphPersistImpl(runtime, { reason = "pending-graph-persist-retry", retryAttempt = 0, scheduleRetryOnFailure = false, ignoreRestoreLock = false, } = {}) { const graphPersistenceState = createGraphPersistenceStateProxy(runtime); const currentGraph = runtime.getCurrentGraph?.() || null; const nativeHydrateInstallPromiseRef = createNativeHydrateInstallPromiseRef(runtime); const nativePersistDeltaInstallPromiseRef = createNativePersistDeltaInstallPromiseRef(runtime); const bmeIndexedDbLatestQueuedRevisionByChatId = runtime.bmeIndexedDbLatestQueuedRevisionByChatId; const bmeIndexedDbWriteInFlightByChatId = runtime.bmeIndexedDbWriteInFlightByChatId; const updateGraphPersistenceState = runtime.updateGraphPersistenceState || ((patch = {}) => runtime.setGraphPersistenceState?.({ ...(runtime.getGraphPersistenceState?.() || {}), ...(patch || {}) })); const AUTHORITY_GRAPH_STORE_KIND = runtime.AUTHORITY_GRAPH_STORE_KIND; const BME_INDEXEDDB_FALLBACK_LOAD_STATE_SET = runtime.BME_INDEXEDDB_FALLBACK_LOAD_STATE_SET; const GRAPH_LOAD_STATES = runtime.GRAPH_LOAD_STATES; const applyAcceptedPendingPersistState = runtime.applyAcceptedPendingPersistState; const applyGraphLoadState = runtime.applyGraphLoadState; const applyIndexedDbEmptyToRuntime = runtime.applyIndexedDbEmptyToRuntime; const applyIndexedDbSnapshotToRuntime = runtime.applyIndexedDbSnapshotToRuntime; const applyPersistDeltaToSnapshot = runtime.applyPersistDeltaToSnapshot; const applyShadowSnapshotToRuntime = runtime.applyShadowSnapshotToRuntime; const areChatIdsEquivalentForResolvedIdentity = runtime.areChatIdsEquivalentForResolvedIdentity; const buildBmeSyncRuntimeOptions = runtime.buildBmeSyncRuntimeOptions; const buildGraphLocalStoreSelectorKey = runtime.buildGraphLocalStoreSelectorKey; const buildGraphPersistResult = runtime.buildGraphPersistResult; const buildPersistDelta = runtime.buildPersistDelta; const buildPersistDeltaFromGraphDirtyState = runtime.buildPersistDeltaFromGraphDirtyState; const buildPersistObservabilitySummary = runtime.buildPersistObservabilitySummary; const buildPersistenceEnvironment = runtime.buildPersistenceEnvironment; const buildSnapshotFromGraph = runtime.buildSnapshotFromGraph; const cacheIndexedDbSnapshot = runtime.cacheIndexedDbSnapshot; const canPersistGraphToMetadataFallback = runtime.canPersistGraphToMetadataFallback; const clearPendingGraphPersistRetry = runtime.clearPendingGraphPersistRetry; const cloneGraphForPersistence = runtime.cloneGraphForPersistence; const cloneRuntimeDebugValue = runtime.cloneRuntimeDebugValue; const createShadowComparisonGraph = runtime.createShadowComparisonGraph; const detectIndexedDbSnapshotCommitMarkerMismatch = runtime.detectIndexedDbSnapshotCommitMarkerMismatch; const detectStaleIndexedDbSnapshotAgainstRuntime = runtime.detectStaleIndexedDbSnapshotAgainstRuntime; const ensureBmeChatManager = runtime.ensureBmeChatManager; const ensureCurrentGraphRuntimeState = runtime.ensureCurrentGraphRuntimeState; const evaluateNativeHydrateGate = runtime.evaluateNativeHydrateGate; const evaluatePersistNativeDeltaGate = runtime.evaluatePersistNativeDeltaGate; const getChatMetadataIntegrity = runtime.getChatMetadataIntegrity; const getContext = runtime.getContext; const getCurrentChatId = runtime.getCurrentChatId; const getGraphPersistedRevision = runtime.getGraphPersistedRevision; const getPreferredGraphLocalStorePresentationSync = runtime.getPreferredGraphLocalStorePresentationSync; const getRequestedGraphLocalStorageMode = runtime.getRequestedGraphLocalStorageMode; const getSettings = runtime.getSettings; const hasMeaningfulRuntimeGraphForChat = runtime.hasMeaningfulRuntimeGraphForChat; const isAuthorityGraphStorePresentation = runtime.isAuthorityGraphStorePresentation; const isGraphLocalStorageModeOpfs = runtime.isGraphLocalStorageModeOpfs; const isIndexedDbSnapshotMeaningful = runtime.isIndexedDbSnapshotMeaningful; const isRestoreLockActive = runtime.isRestoreLockActive; const maybeCaptureGraphShadowSnapshot = runtime.maybeCaptureGraphShadowSnapshot; const maybeClearAcceptedPendingPersistState = runtime.maybeClearAcceptedPendingPersistState; const maybeImportLegacyIndexedDbSnapshotToLocalStore = runtime.maybeImportLegacyIndexedDbSnapshotToLocalStore; const maybeImportLegacyOpfsSnapshotToLocalStore = runtime.maybeImportLegacyOpfsSnapshotToLocalStore; const maybeMigrateLegacyGraphToIndexedDb = runtime.maybeMigrateLegacyGraphToIndexedDb; const maybeRecoverIndexedDbGraphFromStableIdentity = runtime.maybeRecoverIndexedDbGraphFromStableIdentity; const maybeResolveOrphanAcceptedCommitMarker = runtime.maybeResolveOrphanAcceptedCommitMarker; const maybeResumePendingAutoExtraction = runtime.maybeResumePendingAutoExtraction; const normalizeChatIdCandidate = runtime.normalizeChatIdCandidate; const normalizeGraphRuntimeState = runtime.normalizeGraphRuntimeState; const normalizeIndexedDbRevision = runtime.normalizeIndexedDbRevision; const normalizeLoadDiagnosticsMs = runtime.normalizeLoadDiagnosticsMs; const normalizePersistDeltaDiagnosticsMs = runtime.normalizePersistDeltaDiagnosticsMs; const persistGraphToChatMetadata = runtime.persistGraphToChatMetadata; const persistGraphToConfiguredDurableTier = runtime.persistGraphToConfiguredDurableTier; const pruneGraphPersistDirtyState = runtime.pruneGraphPersistDirtyState; const queueGraphPersist = runtime.queueGraphPersist; const queueRuntimeGraphLocalStoreRepair = runtime.queueRuntimeGraphLocalStoreRepair; const readCachedIndexedDbSnapshot = runtime.readCachedIndexedDbSnapshot; const readLoadDiagnosticsNow = runtime.readLoadDiagnosticsNow; const readLocalStoreDiagnosticsSync = runtime.readLocalStoreDiagnosticsSync; const readPersistDeltaDiagnosticsNow = runtime.readPersistDeltaDiagnosticsNow; const recordLocalPersistEarlyFailure = runtime.recordLocalPersistEarlyFailure; const recordPersistMismatchDiagnostic = runtime.recordPersistMismatchDiagnostic; const refreshCurrentChatLocalStoreBinding = runtime.refreshCurrentChatLocalStoreBinding; const rememberResolvedGraphIdentityAlias = runtime.rememberResolvedGraphIdentityAlias; const resolveCompatibleGraphShadowSnapshot = runtime.resolveCompatibleGraphShadowSnapshot; const resolveCurrentChatIdentity = runtime.resolveCurrentChatIdentity; const resolveDbGraphStorePresentation = runtime.resolveDbGraphStorePresentation; const resolveLocalStoreTierFromPresentation = runtime.resolveLocalStoreTierFromPresentation; const resolvePendingPersistGraphSource = runtime.resolvePendingPersistGraphSource; const resolvePendingPersistLastProcessedAssistantFloor = runtime.resolvePendingPersistLastProcessedAssistantFloor; const resolvePersistRevisionFloor = runtime.resolvePersistRevisionFloor; const resolveSnapshotGraphStorePresentation = runtime.resolveSnapshotGraphStorePresentation; const schedulePendingGraphPersistRetry = runtime.schedulePendingGraphPersistRetry; const scheduleUpload = runtime.scheduleUpload; const shouldPreferShadowSnapshotOverOfficial = runtime.shouldPreferShadowSnapshotOverOfficial; const stampGraphPersistenceMeta = runtime.stampGraphPersistenceMeta; const syncCommitMarkerToPersistenceState = runtime.syncCommitMarkerToPersistenceState; const updateLoadDiagnostics = runtime.updateLoadDiagnostics; const updatePersistDeltaDiagnostics = runtime.updatePersistDeltaDiagnostics; const console = runtime.console || globalThis.console; ensureCurrentGraphRuntimeState(); if (!ignoreRestoreLock && isRestoreLockActive()) { return buildGraphPersistResult({ saved: false, blocked: true, accepted: false, reason: "restore-lock-active", revision: graphPersistenceState.revision, saveMode: graphPersistenceState.lastPersistMode, storageTier: "none", }); } if (!graphPersistenceState.pendingPersist) { clearPendingGraphPersistRetry(); return buildGraphPersistResult({ saved: false, blocked: false, accepted: false, reason: "no-pending-persist", revision: graphPersistenceState.revision, saveMode: graphPersistenceState.lastPersistMode, storageTier: "none", }); } if (maybeClearAcceptedPendingPersistState(reason)) { return buildGraphPersistResult({ saved: true, blocked: false, accepted: true, reason: `${String(reason || "pending-graph-persist-retry")}:accepted-revision`, revision: Math.max( Number(graphPersistenceState.lastAcceptedRevision || 0), Number(graphPersistenceState.revision || 0), ), saveMode: "accepted-revision-reconcile", storageTier: String(graphPersistenceState.acceptedStorageTier || "none"), acceptedBy: String(graphPersistenceState.acceptedStorageTier || "none"), }); } const context = getContext(); const activeChatId = normalizeChatIdCandidate(getCurrentChatId(context)); const queuedChatId = normalizeChatIdCandidate( graphPersistenceState.queuedPersistChatId || graphPersistenceState.chatId || activeChatId, ); const currentIdentity = resolveCurrentChatIdentity(context); if (!currentGraph || !context || !activeChatId || !queuedChatId) { if (scheduleRetryOnFailure) { schedulePendingGraphPersistRetry(reason, Number(retryAttempt) + 1); } return buildGraphPersistResult({ saved: false, queued: true, blocked: true, accepted: false, reason: "pending-persist-context-unavailable", revision: Math.max( Number(graphPersistenceState.queuedPersistRevision || 0), Number(graphPersistenceState.revision || 0), ), saveMode: graphPersistenceState.queuedPersistMode, storageTier: "none", }); } if ( !areChatIdsEquivalentForResolvedIdentity( queuedChatId, activeChatId, currentIdentity, ) && !areChatIdsEquivalentForResolvedIdentity( activeChatId, queuedChatId, currentIdentity, ) ) { if (scheduleRetryOnFailure) { schedulePendingGraphPersistRetry(reason, Number(retryAttempt) + 1); } return buildGraphPersistResult({ saved: false, queued: true, blocked: true, accepted: false, reason: "queued-chat-mismatch", revision: Math.max( Number(graphPersistenceState.queuedPersistRevision || 0), Number(graphPersistenceState.revision || 0), ), saveMode: graphPersistenceState.queuedPersistMode, storageTier: "none", }); } const requestedLocalStoreMode = getRequestedGraphLocalStorageMode( getSettings(), ); if ( requestedLocalStoreMode === "auto" || isGraphLocalStorageModeOpfs(requestedLocalStoreMode) ) { await refreshCurrentChatLocalStoreBinding({ chatId: activeChatId, forceCapabilityRefresh: true, reopenCurrentDb: true, source: reason, }); } const pendingPersistGraphSource = resolvePendingPersistGraphSource( queuedChatId, ); const pendingPersistGraph = pendingPersistGraphSource?.graph || currentGraph; const pendingPersistGraphDetached = Boolean(pendingPersistGraph) && typeof pendingPersistGraph === "object" && pendingPersistGraph !== currentGraph; const targetRevision = Math.max( Number(graphPersistenceState.queuedPersistRevision || 0), Number(graphPersistenceState.revision || 0), Number(graphPersistenceState.lastPersistedRevision || 0), Number(pendingPersistGraphSource?.revision || 0), Number(getGraphPersistedRevision(pendingPersistGraph) || 0), ); const lastProcessedAssistantFloor = resolvePendingPersistLastProcessedAssistantFloor(); const acceptedPersistResult = await persistGraphToConfiguredDurableTier( context, pendingPersistGraph, { chatId: activeChatId, revision: targetRevision, reason, lastProcessedAssistantFloor, graphDetached: pendingPersistGraphDetached, }, ); if (acceptedPersistResult?.accepted) { applyAcceptedPendingPersistState(acceptedPersistResult, { lastProcessedAssistantFloor, persistedGraph: pendingPersistGraph, }); void maybeResumePendingAutoExtraction( `pending-persist-resolved:${acceptedPersistResult.acceptedBy || acceptedPersistResult.storageTier || "accepted"}`, ); return acceptedPersistResult; } let recoverableTier = "none"; if (canPersistGraphToMetadataFallback(context, pendingPersistGraph)) { const metadataReason = `${reason}:metadata-full-fallback`; const metadataResult = persistGraphToChatMetadata(context, { reason: metadataReason, revision: targetRevision, immediate: true, graph: pendingPersistGraph, }); if (metadataResult?.saved) { recoverableTier = "metadata-full"; } } if ( recoverableTier === "none" && maybeCaptureGraphShadowSnapshot(`${reason}:shadow-fallback`, { graph: pendingPersistGraph, chatId: activeChatId, revision: targetRevision, }) ) { recoverableTier = "shadow"; } const queuedReason = `${reason}:still-pending`; const queuedResult = queueGraphPersist(queuedReason, targetRevision, { immediate: graphPersistenceState.queuedPersistMode !== "debounced", graph: pendingPersistGraph, chatId: activeChatId, captureShadow: recoverableTier === "none", recoverableTier, }); if (recoverableTier !== "none") { updateGraphPersistenceState({ lastPersistReason: queuedReason, lastRecoverableStorageTier: recoverableTier, }); } if (scheduleRetryOnFailure && recoverableTier === "none") { schedulePendingGraphPersistRetry(reason, Number(retryAttempt) + 1); } return buildGraphPersistResult({ saved: false, queued: true, blocked: true, accepted: false, recoverable: recoverableTier !== "none" || queuedResult?.recoverable === true, reason: queuedReason, revision: Number(queuedResult?.revision || targetRevision), saveMode: String( queuedResult?.saveMode || graphPersistenceState.queuedPersistMode || "immediate", ), storageTier: recoverableTier !== "none" ? recoverableTier : String(queuedResult?.storageTier || "none"), }); } export async function saveGraphToIndexedDbImpl(runtime, chatId, graph, { revision = 0, reason = "graph-save", persistRole = "primary", scheduleCloudUpload: scheduleCloudUploadOption = undefined, persistDelta = null, graphSnapshot = null, persistSnapshot = null, sourceGraph = null, } = {}, ) { const graphPersistenceState = createGraphPersistenceStateProxy(runtime); const currentGraph = runtime.getCurrentGraph?.() || null; const nativeHydrateInstallPromiseRef = createNativeHydrateInstallPromiseRef(runtime); const nativePersistDeltaInstallPromiseRef = createNativePersistDeltaInstallPromiseRef(runtime); const bmeIndexedDbLatestQueuedRevisionByChatId = runtime.bmeIndexedDbLatestQueuedRevisionByChatId; const bmeIndexedDbWriteInFlightByChatId = runtime.bmeIndexedDbWriteInFlightByChatId; const updateGraphPersistenceState = runtime.updateGraphPersistenceState || ((patch = {}) => runtime.setGraphPersistenceState?.({ ...(runtime.getGraphPersistenceState?.() || {}), ...(patch || {}) })); const AUTHORITY_GRAPH_STORE_KIND = runtime.AUTHORITY_GRAPH_STORE_KIND; const BME_INDEXEDDB_FALLBACK_LOAD_STATE_SET = runtime.BME_INDEXEDDB_FALLBACK_LOAD_STATE_SET; const GRAPH_LOAD_STATES = runtime.GRAPH_LOAD_STATES; const applyAcceptedPendingPersistState = runtime.applyAcceptedPendingPersistState; const applyGraphLoadState = runtime.applyGraphLoadState; const applyIndexedDbEmptyToRuntime = runtime.applyIndexedDbEmptyToRuntime; const applyIndexedDbSnapshotToRuntime = runtime.applyIndexedDbSnapshotToRuntime; const applyPersistDeltaToSnapshot = runtime.applyPersistDeltaToSnapshot; const applyShadowSnapshotToRuntime = runtime.applyShadowSnapshotToRuntime; const areChatIdsEquivalentForResolvedIdentity = runtime.areChatIdsEquivalentForResolvedIdentity; const buildBmeSyncRuntimeOptions = runtime.buildBmeSyncRuntimeOptions; const buildGraphLocalStoreSelectorKey = runtime.buildGraphLocalStoreSelectorKey; const buildGraphPersistResult = runtime.buildGraphPersistResult; const buildPersistDelta = runtime.buildPersistDelta; const buildPersistDeltaFromGraphDirtyState = runtime.buildPersistDeltaFromGraphDirtyState; const buildPersistObservabilitySummary = runtime.buildPersistObservabilitySummary; const buildPersistenceEnvironment = runtime.buildPersistenceEnvironment; const buildSnapshotFromGraph = runtime.buildSnapshotFromGraph; const cacheIndexedDbSnapshot = runtime.cacheIndexedDbSnapshot; const canPersistGraphToMetadataFallback = runtime.canPersistGraphToMetadataFallback; const clearPendingGraphPersistRetry = runtime.clearPendingGraphPersistRetry; const cloneGraphForPersistence = runtime.cloneGraphForPersistence; const cloneRuntimeDebugValue = runtime.cloneRuntimeDebugValue; const createShadowComparisonGraph = runtime.createShadowComparisonGraph; const detectIndexedDbSnapshotCommitMarkerMismatch = runtime.detectIndexedDbSnapshotCommitMarkerMismatch; const detectStaleIndexedDbSnapshotAgainstRuntime = runtime.detectStaleIndexedDbSnapshotAgainstRuntime; const ensureBmeChatManager = runtime.ensureBmeChatManager; const ensureCurrentGraphRuntimeState = runtime.ensureCurrentGraphRuntimeState; const evaluateNativeHydrateGate = runtime.evaluateNativeHydrateGate; const evaluatePersistNativeDeltaGate = runtime.evaluatePersistNativeDeltaGate; const getChatMetadataIntegrity = runtime.getChatMetadataIntegrity; const getContext = runtime.getContext; const getCurrentChatId = runtime.getCurrentChatId; const getGraphPersistedRevision = runtime.getGraphPersistedRevision; const getPreferredGraphLocalStorePresentationSync = runtime.getPreferredGraphLocalStorePresentationSync; const getRequestedGraphLocalStorageMode = runtime.getRequestedGraphLocalStorageMode; const getSettings = runtime.getSettings; const hasMeaningfulRuntimeGraphForChat = runtime.hasMeaningfulRuntimeGraphForChat; const isAuthorityGraphStorePresentation = runtime.isAuthorityGraphStorePresentation; const isGraphLocalStorageModeOpfs = runtime.isGraphLocalStorageModeOpfs; const isIndexedDbSnapshotMeaningful = runtime.isIndexedDbSnapshotMeaningful; const isRestoreLockActive = runtime.isRestoreLockActive; const maybeCaptureGraphShadowSnapshot = runtime.maybeCaptureGraphShadowSnapshot; const maybeClearAcceptedPendingPersistState = runtime.maybeClearAcceptedPendingPersistState; const maybeImportLegacyIndexedDbSnapshotToLocalStore = runtime.maybeImportLegacyIndexedDbSnapshotToLocalStore; const maybeImportLegacyOpfsSnapshotToLocalStore = runtime.maybeImportLegacyOpfsSnapshotToLocalStore; const maybeMigrateLegacyGraphToIndexedDb = runtime.maybeMigrateLegacyGraphToIndexedDb; const maybeRecoverIndexedDbGraphFromStableIdentity = runtime.maybeRecoverIndexedDbGraphFromStableIdentity; const maybeResolveOrphanAcceptedCommitMarker = runtime.maybeResolveOrphanAcceptedCommitMarker; const maybeResumePendingAutoExtraction = runtime.maybeResumePendingAutoExtraction; const normalizeChatIdCandidate = runtime.normalizeChatIdCandidate; const normalizeGraphRuntimeState = runtime.normalizeGraphRuntimeState; const normalizeIndexedDbRevision = runtime.normalizeIndexedDbRevision; const normalizeLoadDiagnosticsMs = runtime.normalizeLoadDiagnosticsMs; const normalizePersistDeltaDiagnosticsMs = runtime.normalizePersistDeltaDiagnosticsMs; const persistGraphToChatMetadata = runtime.persistGraphToChatMetadata; const persistGraphToConfiguredDurableTier = runtime.persistGraphToConfiguredDurableTier; const pruneGraphPersistDirtyState = runtime.pruneGraphPersistDirtyState; const queueGraphPersist = runtime.queueGraphPersist; const queueRuntimeGraphLocalStoreRepair = runtime.queueRuntimeGraphLocalStoreRepair; const readCachedIndexedDbSnapshot = runtime.readCachedIndexedDbSnapshot; const readLoadDiagnosticsNow = runtime.readLoadDiagnosticsNow; const readLocalStoreDiagnosticsSync = runtime.readLocalStoreDiagnosticsSync; const readPersistDeltaDiagnosticsNow = runtime.readPersistDeltaDiagnosticsNow; const recordLocalPersistEarlyFailure = runtime.recordLocalPersistEarlyFailure; const recordPersistMismatchDiagnostic = runtime.recordPersistMismatchDiagnostic; const refreshCurrentChatLocalStoreBinding = runtime.refreshCurrentChatLocalStoreBinding; const rememberResolvedGraphIdentityAlias = runtime.rememberResolvedGraphIdentityAlias; const resolveCompatibleGraphShadowSnapshot = runtime.resolveCompatibleGraphShadowSnapshot; const resolveCurrentChatIdentity = runtime.resolveCurrentChatIdentity; const resolveDbGraphStorePresentation = runtime.resolveDbGraphStorePresentation; const resolveLocalStoreTierFromPresentation = runtime.resolveLocalStoreTierFromPresentation; const resolvePendingPersistGraphSource = runtime.resolvePendingPersistGraphSource; const resolvePendingPersistLastProcessedAssistantFloor = runtime.resolvePendingPersistLastProcessedAssistantFloor; const resolvePersistRevisionFloor = runtime.resolvePersistRevisionFloor; const resolveSnapshotGraphStorePresentation = runtime.resolveSnapshotGraphStorePresentation; const schedulePendingGraphPersistRetry = runtime.schedulePendingGraphPersistRetry; const scheduleUpload = runtime.scheduleUpload; const shouldPreferShadowSnapshotOverOfficial = runtime.shouldPreferShadowSnapshotOverOfficial; const stampGraphPersistenceMeta = runtime.stampGraphPersistenceMeta; const syncCommitMarkerToPersistenceState = runtime.syncCommitMarkerToPersistenceState; const updateLoadDiagnostics = runtime.updateLoadDiagnostics; const updatePersistDeltaDiagnostics = runtime.updatePersistDeltaDiagnostics; const console = runtime.console || globalThis.console; const normalizedChatId = normalizeChatIdCandidate(chatId); if (!normalizedChatId || (!graph && !persistDelta)) { recordLocalPersistEarlyFailure("indexeddb-missing-chat-graph-or-delta", { chatId: normalizedChatId, revision, }); return { saved: false, chatId: normalizedChatId, reason: "indexeddb-missing-chat-graph-or-delta", revision: normalizeIndexedDbRevision(revision), }; } const context = getContext(); let db = null; let localStore = getPreferredGraphLocalStorePresentationSync(); try { const manager = ensureBmeChatManager(); if (!manager) { recordLocalPersistEarlyFailure("indexeddb-manager-unavailable", { chatId: normalizedChatId, revision, }); return { saved: false, chatId: normalizedChatId, reason: "indexeddb-manager-unavailable", revision: normalizeIndexedDbRevision(revision), }; } db = await manager.getCurrentDb(normalizedChatId); if (!db) { recordLocalPersistEarlyFailure("indexeddb-db-unavailable", { chatId: normalizedChatId, revision, }); return { saved: false, chatId: normalizedChatId, reason: "indexeddb-db-unavailable", revision: normalizeIndexedDbRevision(revision), }; } localStore = resolveDbGraphStorePresentation(db); const persistenceEnvironment = buildPersistenceEnvironment(context, localStore); const localStoreTier = resolveLocalStoreTierFromPresentation(localStore); const currentIdentity = resolveCurrentChatIdentity(context); const requestedRevision = resolvePersistRevisionFloor(revision, graph); const currentSettings = getSettings(); const shouldScheduleCloudUpload = scheduleCloudUploadOption != null ? scheduleCloudUploadOption === true : persistenceEnvironment.primaryStorageTier !== "authority-sql" && persistenceEnvironment.hostProfile !== "luker" && persistRole !== "cache-mirror"; const directPersistDelta = persistDelta && typeof persistDelta === "object" && !Array.isArray(persistDelta) ? cloneRuntimeDebugValue(persistDelta, persistDelta) : null; const detachedGraphSnapshot = graphSnapshot && typeof graphSnapshot === "object" && !Array.isArray(graphSnapshot) ? graphSnapshot : null; const prebuiltPersistSnapshot = persistSnapshot && typeof persistSnapshot === "object" && !Array.isArray(persistSnapshot) ? persistSnapshot : null; const sourceGraphInput = sourceGraph && typeof sourceGraph === "object" && !Array.isArray(sourceGraph) ? sourceGraph : null; const persistGraphInput = detachedGraphSnapshot || graph; let baseSnapshot = null; let snapshot = prebuiltPersistSnapshot; let delta = directPersistDelta; let persistDeltaBuildDiagnostics = null; let dirtyPersistDeltaVersion = 0; let dirtyPersistUsed = false; let nativePersistModuleStatus = null; let nativePersistPreloadStatus = "not-requested"; let nativePersistPreloadError = ""; let nativePersistPreloadMs = 0; let baseSnapshotReadMs = 0; let graphSnapshotBuildMs = 0; let snapshotBuildDiagnostics = null; const persistDeltaStartedAt = readPersistDeltaDiagnosticsNow(); if (!delta) { const baseSnapshotReadStartedAt = readPersistDeltaDiagnosticsNow(); baseSnapshot = readCachedIndexedDbSnapshot(normalizedChatId, localStore); if (!baseSnapshot) { baseSnapshot = await db.exportSnapshot(); } baseSnapshotReadMs = readPersistDeltaDiagnosticsNow() - baseSnapshotReadStartedAt; if (persistGraphInput) { delta = buildPersistDeltaFromGraphDirtyState(baseSnapshot, persistGraphInput, { chatId: normalizedChatId, revision: requestedRevision, lastModified: Date.now(), meta: { storagePrimary: localStore.storagePrimary, storageMode: localStore.storageMode, lastMutationReason: String(reason || "graph-save"), integrity: currentIdentity.integrity || graphPersistenceState.metadataIntegrity, hostChatId: currentIdentity.hostChatId || "", }, onDiagnostics(snapshotValue) { persistDeltaBuildDiagnostics = snapshotValue && typeof snapshotValue === "object" && !Array.isArray(snapshotValue) ? snapshotValue : null; }, }); dirtyPersistUsed = Boolean(delta); dirtyPersistDeltaVersion = Math.max( 0, Math.floor(Number(persistDeltaBuildDiagnostics?.dirtyStateVersion || 0)), ); if (dirtyPersistUsed) { snapshot = applyPersistDeltaToSnapshot(baseSnapshot, delta, { chatId: normalizedChatId, revision: requestedRevision, lastModified: Date.now(), reason: String(reason || "graph-save"), }); } } if (!snapshot) { const graphSnapshotBuildStartedAt = readPersistDeltaDiagnosticsNow(); snapshot = buildSnapshotFromGraph(persistGraphInput, { chatId: normalizedChatId, revision: requestedRevision, baseSnapshot, lastModified: Date.now(), meta: { storagePrimary: localStore.storagePrimary, storageMode: localStore.storageMode, lastMutationReason: String(reason || "graph-save"), integrity: currentIdentity.integrity || graphPersistenceState.metadataIntegrity, hostChatId: currentIdentity.hostChatId || "", }, onDiagnostics(snapshotValue) { snapshotBuildDiagnostics = snapshotValue && typeof snapshotValue === "object" && !Array.isArray(snapshotValue) ? snapshotValue : null; }, }); graphSnapshotBuildMs = readPersistDeltaDiagnosticsNow() - graphSnapshotBuildStartedAt; } } const nativePersistBridgeMode = String( currentSettings.persistNativeDeltaBridgeMode || "json", ); const nativePersistRequested = !directPersistDelta && !dirtyPersistUsed && currentSettings.persistUseNativeDelta === true; const nativePersistForceDisabled = currentSettings.graphNativeForceDisable === true; const nativePersistGate = !delta && baseSnapshot && snapshot ? evaluatePersistNativeDeltaGate(baseSnapshot, snapshot, currentSettings) : { allowed: false, reasons: [ directPersistDelta ? "direct-delta" : dirtyPersistUsed ? "dirty-runtime" : "delta-prebuilt", ], minSnapshotRecords: Number( currentSettings.persistNativeDeltaThresholdRecords || 0, ), minStructuralDelta: Number( currentSettings.persistNativeDeltaThresholdStructuralDelta || 0, ), minCombinedSerializedChars: Number( currentSettings.persistNativeDeltaThresholdSerializedChars || 0, ), beforeRecordCount: 0, afterRecordCount: 0, maxSnapshotRecords: 0, structuralDelta: 0, }; const shouldUseNativePersistDelta = nativePersistRequested && nativePersistForceDisabled !== true && nativePersistGate.allowed; if (!directPersistDelta) { nativePersistPreloadStatus = nativePersistRequested ? nativePersistForceDisabled ? "force-disabled" : nativePersistGate.allowed ? "pending" : "gated-out" : "not-requested"; } updatePersistDeltaDiagnostics({ chatId: normalizedChatId, saveReason: String(reason || "graph-save"), requestedRevision, requestedNative: nativePersistRequested, requestedBridgeMode: directPersistDelta ? "direct-delta" : dirtyPersistUsed ? "dirty-runtime" : nativePersistBridgeMode, nativeForceDisabled: nativePersistForceDisabled, nativeFailOpen: currentSettings.nativeEngineFailOpen !== false, gateAllowed: directPersistDelta || dirtyPersistUsed ? true : nativePersistGate.allowed, gateReasons: cloneRuntimeDebugValue( directPersistDelta ? ["direct-delta"] : dirtyPersistUsed ? ["dirty-runtime"] : nativePersistGate.reasons, [], ), preloadGateAllowed: directPersistDelta || dirtyPersistUsed ? true : nativePersistGate.allowed, preloadGateReasons: cloneRuntimeDebugValue( directPersistDelta ? ["direct-delta"] : dirtyPersistUsed ? ["dirty-runtime"] : nativePersistGate.reasons, [], ), minSnapshotRecords: nativePersistGate.minSnapshotRecords, minStructuralDelta: nativePersistGate.minStructuralDelta, minCombinedSerializedChars: nativePersistGate.minCombinedSerializedChars, beforeRecordCount: nativePersistGate.beforeRecordCount, afterRecordCount: nativePersistGate.afterRecordCount, maxSnapshotRecords: nativePersistGate.maxSnapshotRecords, structuralDelta: nativePersistGate.structuralDelta, preloadStatus: nativePersistPreloadStatus, preloadMs: 0, preloadError: "", status: "building", path: directPersistDelta ? "direct-delta" : dirtyPersistUsed ? "dirty-runtime" : undefined, }); if (!directPersistDelta && shouldUseNativePersistDelta) { const preloadStartedAt = readPersistDeltaDiagnosticsNow(); try { if (!nativePersistDeltaInstallPromiseRef.value) { nativePersistDeltaInstallPromiseRef.value = importNativeCore(runtime) .then((module) => module?.installNativePersistDeltaHook?.()) .catch((error) => { nativePersistDeltaInstallPromiseRef.value = null; throw error; }); } nativePersistModuleStatus = await nativePersistDeltaInstallPromiseRef.value; nativePersistPreloadStatus = nativePersistModuleStatus?.loaded ? "loaded" : "not-loaded"; nativePersistPreloadMs = readPersistDeltaDiagnosticsNow() - preloadStartedAt; } catch (error) { nativePersistPreloadStatus = "failed"; nativePersistPreloadMs = readPersistDeltaDiagnosticsNow() - preloadStartedAt; nativePersistPreloadError = error?.message || String(error); if (currentSettings.nativeEngineFailOpen !== false) { console.warn( "[ST-BME] native persist delta preload failed, fallback to JS delta:", error, ); } else { throw error; } } } if (!delta) { delta = buildPersistDelta(baseSnapshot, snapshot, { useNativeDelta: shouldUseNativePersistDelta, nativeFailOpen: currentSettings.nativeEngineFailOpen !== false, persistNativeDeltaThresholdRecords: currentSettings.persistNativeDeltaThresholdRecords, persistNativeDeltaThresholdStructuralDelta: currentSettings.persistNativeDeltaThresholdStructuralDelta, persistNativeDeltaThresholdSerializedChars: currentSettings.persistNativeDeltaThresholdSerializedChars, persistNativeDeltaBridgeMode: nativePersistBridgeMode, onDiagnostics(snapshotValue) { persistDeltaBuildDiagnostics = snapshotValue; }, }); } else if (!persistDeltaBuildDiagnostics) { persistDeltaBuildDiagnostics = { requestedNative: false, requestedBridgeMode: directPersistDelta ? "direct-delta" : dirtyPersistUsed ? "dirty-runtime" : "prebuilt-delta", usedNative: false, path: directPersistDelta ? "direct-delta" : dirtyPersistUsed ? "dirty-runtime" : "prebuilt-delta", gateAllowed: true, gateReasons: [ directPersistDelta ? "direct-delta" : dirtyPersistUsed ? "dirty-runtime" : "prebuilt-delta", ], nativeAttemptStatus: "not-requested", nativeError: "", beforeRecordCount: Number( delta?.countDelta?.previous?.nodes || 0, ) + Number(delta?.countDelta?.previous?.edges || 0), afterRecordCount: Number( delta?.countDelta?.next?.nodes || 0, ) + Number(delta?.countDelta?.next?.edges || 0), maxSnapshotRecords: Math.max( Number(delta?.countDelta?.previous?.nodes || 0) + Number(delta?.countDelta?.previous?.edges || 0), Number(delta?.countDelta?.next?.nodes || 0) + Number(delta?.countDelta?.next?.edges || 0), ), structuralDelta: Number(delta?.upsertNodes?.length || 0) + Number(delta?.upsertEdges?.length || 0) + Number(delta?.deleteNodeIds?.length || 0) + Number(delta?.deleteEdgeIds?.length || 0), beforeSerializedChars: 0, afterSerializedChars: 0, combinedSerializedChars: 0, prepareMs: 0, nativeAttemptMs: 0, lookupMs: 0, jsDiffMs: 0, hydrateMs: 0, serializationCacheObjectHits: 0, serializationCacheTokenHits: 0, serializationCacheMisses: 0, serializationCacheHits: 0, preparedRecordSetCacheHits: 0, preparedRecordSetCacheMisses: 0, minCombinedSerializedChars: 0, upsertNodeCount: Number(delta?.upsertNodes?.length || 0), upsertEdgeCount: Number(delta?.upsertEdges?.length || 0), deleteNodeCount: Number(delta?.deleteNodeIds?.length || 0), deleteEdgeCount: Number(delta?.deleteEdgeIds?.length || 0), tombstoneCount: Number(delta?.tombstones?.length || 0), dirtyStateVersion: dirtyPersistDeltaVersion, }; } const commitResult = await db.commitDelta(delta, { reason, requestedRevision, markSyncDirty: true, committedSnapshot: snapshot, }); const commitDiagnostics = commitResult?.diagnostics && typeof commitResult.diagnostics === "object" && !Array.isArray(commitResult.diagnostics) ? cloneRuntimeDebugValue(commitResult.diagnostics, {}) : null; const committedRevision = normalizeIndexedDbRevision( commitResult?.revision, requestedRevision, ); const committedLastModified = Number(commitResult?.lastModified || Date.now()); let scheduleUploadWarning = ""; if (persistGraphInput) { if (!snapshot) { const graphSnapshotBuildStartedAt = readPersistDeltaDiagnosticsNow(); snapshot = buildSnapshotFromGraph(persistGraphInput, { chatId: normalizedChatId, revision: committedRevision, baseSnapshot: baseSnapshot || undefined, lastModified: committedLastModified, meta: { storagePrimary: localStore.storagePrimary, storageMode: localStore.storageMode, lastMutationReason: String(reason || "graph-save"), integrity: currentIdentity.integrity || graphPersistenceState.metadataIntegrity, hostChatId: currentIdentity.hostChatId || "", }, onDiagnostics(snapshotValue) { snapshotBuildDiagnostics = snapshotValue && typeof snapshotValue === "object" && !Array.isArray(snapshotValue) ? snapshotValue : null; }, }); graphSnapshotBuildMs += readPersistDeltaDiagnosticsNow() - graphSnapshotBuildStartedAt; } if (!snapshot.meta || typeof snapshot.meta !== "object" || Array.isArray(snapshot.meta)) { snapshot.meta = {}; } snapshot.meta.revision = committedRevision; snapshot.meta.lastModified = committedLastModified; snapshot.meta.lastMutationReason = String(reason || "graph-save"); snapshot.meta.storagePrimary = localStore.storagePrimary; snapshot.meta.storageMode = localStore.storageMode; if (localStore.storagePrimary !== AUTHORITY_GRAPH_STORE_KIND) { cacheIndexedDbSnapshot(normalizedChatId, snapshot); } } if (dirtyPersistDeltaVersion > 0) { pruneGraphPersistDirtyState(graph, dirtyPersistDeltaVersion); if (sourceGraphInput && sourceGraphInput !== graph) { pruneGraphPersistDirtyState(sourceGraphInput, dirtyPersistDeltaVersion); } } if (graph === currentGraph) { stampGraphPersistenceMeta(currentGraph, { revision: committedRevision, reason: String(reason || "graph-save"), chatId: normalizedChatId, integrity: currentIdentity.integrity || getChatMetadataIntegrity(context) || graphPersistenceState.metadataIntegrity, }); } if (shouldScheduleCloudUpload) { try { scheduleUpload( normalizedChatId, buildBmeSyncRuntimeOptions({ trigger: `graph-mutation:${String(reason || "graph-save")}`, }), ); } catch (error) { scheduleUploadWarning = error?.message || String(error) || "schedule-upload-failed"; console.warn( `[ST-BME] ${localStore.statusLabel} 已写入,但同步上传调度失败:`, error, ); } } const persistTotalMs = readPersistDeltaDiagnosticsNow() - persistDeltaStartedAt; const persistAccountedMs = Number(nativePersistPreloadMs || 0) + Number(baseSnapshotReadMs || 0) + Number(graphSnapshotBuildMs || 0) + Number(persistDeltaBuildDiagnostics?.buildMs || 0) + Number(commitDiagnostics?.queueWaitMs || 0) + Number(commitDiagnostics?.commitMs || 0); const persistDeltaDiagnostics = { ...cloneRuntimeDebugValue(persistDeltaBuildDiagnostics, {}), chatId: normalizedChatId, saveReason: String(reason || "graph-save"), requestedRevision, requestedNative: nativePersistRequested, requestedBridgeMode: persistDeltaBuildDiagnostics?.requestedBridgeMode || (directPersistDelta ? "direct-delta" : nativePersistBridgeMode), buildRequestedNative: Boolean(persistDeltaBuildDiagnostics?.requestedNative), nativeForceDisabled: nativePersistForceDisabled, nativeFailOpen: currentSettings.nativeEngineFailOpen !== false, gateAllowed: persistDeltaBuildDiagnostics?.gateAllowed ?? (directPersistDelta ? true : nativePersistGate.allowed), gateReasons: cloneRuntimeDebugValue( persistDeltaBuildDiagnostics?.gateReasons, directPersistDelta ? ["direct-delta"] : nativePersistGate.reasons, ), preloadGateAllowed: directPersistDelta ? true : nativePersistGate.allowed, preloadGateReasons: cloneRuntimeDebugValue( directPersistDelta ? ["direct-delta"] : nativePersistGate.reasons, [], ), minSnapshotRecords: nativePersistGate.minSnapshotRecords, minStructuralDelta: nativePersistGate.minStructuralDelta, minCombinedSerializedChars: persistDeltaBuildDiagnostics?.minCombinedSerializedChars ?? nativePersistGate.minCombinedSerializedChars, beforeRecordCount: persistDeltaBuildDiagnostics?.beforeRecordCount ?? nativePersistGate.beforeRecordCount, afterRecordCount: persistDeltaBuildDiagnostics?.afterRecordCount ?? nativePersistGate.afterRecordCount, maxSnapshotRecords: persistDeltaBuildDiagnostics?.maxSnapshotRecords ?? nativePersistGate.maxSnapshotRecords, structuralDelta: persistDeltaBuildDiagnostics?.structuralDelta ?? nativePersistGate.structuralDelta, preloadStatus: nativePersistPreloadStatus, preloadMs: nativePersistPreloadMs, preloadError: nativePersistPreloadError, moduleLoaded: Boolean(nativePersistModuleStatus?.loaded), moduleSource: String(nativePersistModuleStatus?.source || ""), moduleError: String( nativePersistModuleStatus?.error || nativePersistPreloadError || "", ), baseSnapshotReadMs: normalizePersistDeltaDiagnosticsMs(baseSnapshotReadMs), snapshotBuildMs: normalizePersistDeltaDiagnosticsMs(graphSnapshotBuildMs), snapshotNodesMs: normalizePersistDeltaDiagnosticsMs( snapshotBuildDiagnostics?.nodesMs, ), snapshotEdgesMs: normalizePersistDeltaDiagnosticsMs( snapshotBuildDiagnostics?.edgesMs, ), snapshotTombstonesMs: normalizePersistDeltaDiagnosticsMs( snapshotBuildDiagnostics?.tombstonesMs, ), snapshotStateMs: normalizePersistDeltaDiagnosticsMs( snapshotBuildDiagnostics?.stateMs, ), snapshotMetaMs: normalizePersistDeltaDiagnosticsMs( snapshotBuildDiagnostics?.metaMs, ), snapshotNodeCount: Math.max( 0, Math.floor(Number(snapshotBuildDiagnostics?.nodeCount || 0)), ), snapshotEdgeCount: Math.max( 0, Math.floor(Number(snapshotBuildDiagnostics?.edgeCount || 0)), ), snapshotTombstoneCount: Math.max( 0, Math.floor(Number(snapshotBuildDiagnostics?.tombstoneCount || 0)), ), commitStorageKind: String( commitDiagnostics?.storageKind || localStore.storagePrimary || "", ), commitStoreMode: String( commitDiagnostics?.storeMode || localStore.storageMode || "", ), commitQueueWaitMs: normalizePersistDeltaDiagnosticsMs( commitDiagnostics?.queueWaitMs, ), commitMs: normalizePersistDeltaDiagnosticsMs(commitDiagnostics?.commitMs), commitTxMs: normalizePersistDeltaDiagnosticsMs(commitDiagnostics?.txMs), commitSnapshotReadMs: normalizePersistDeltaDiagnosticsMs( commitDiagnostics?.snapshotReadMs, ), commitSnapshotWriteMs: normalizePersistDeltaDiagnosticsMs( commitDiagnostics?.snapshotWriteMs, ), commitManifestReadMs: normalizePersistDeltaDiagnosticsMs( commitDiagnostics?.manifestReadMs, ), commitWalSerializeMs: normalizePersistDeltaDiagnosticsMs( commitDiagnostics?.walSerializeMs, ), commitWalFileWriteMs: normalizePersistDeltaDiagnosticsMs( commitDiagnostics?.walFileWriteMs, ), commitWalWriteMs: normalizePersistDeltaDiagnosticsMs( commitDiagnostics?.walWriteMs, ), commitManifestSerializeMs: normalizePersistDeltaDiagnosticsMs( commitDiagnostics?.manifestSerializeMs, ), commitManifestFileWriteMs: normalizePersistDeltaDiagnosticsMs( commitDiagnostics?.manifestFileWriteMs, ), commitManifestWriteMs: normalizePersistDeltaDiagnosticsMs( commitDiagnostics?.manifestWriteMs, ), commitCacheApplyMs: normalizePersistDeltaDiagnosticsMs( commitDiagnostics?.cacheApplyMs, ), commitPayloadBytes: Math.max( 0, Math.floor(Number(commitDiagnostics?.payloadBytes || 0)), ), commitWalBytes: Math.max( 0, Math.floor(Number(commitDiagnostics?.walBytes || 0)), ), commitRuntimeMetaKeyCount: Math.max( 0, Math.floor(Number(commitDiagnostics?.runtimeMetaKeyCount || 0)), ), status: "committed", commitRevision: normalizeIndexedDbRevision( commitResult?.revision, requestedRevision, ), commitDelta: cloneRuntimeDebugValue(commitResult?.delta, null), totalMs: normalizePersistDeltaDiagnosticsMs(persistTotalMs), untrackedMs: normalizePersistDeltaDiagnosticsMs( Math.max(0, persistTotalMs - persistAccountedMs), ), }; persistDeltaDiagnostics.fallbackReason = persistDeltaDiagnostics.requestedNative && !persistDeltaDiagnostics.usedNative ? String( (persistDeltaDiagnostics.preloadStatus !== "loaded" && persistDeltaDiagnostics.preloadStatus !== "pending" ? persistDeltaDiagnostics.preloadStatus : persistDeltaDiagnostics.nativeAttemptStatus) || "js", ) : ""; const persistObservability = buildPersistObservabilitySummary( persistDeltaDiagnostics, ); persistDeltaDiagnostics.pathKey = String( persistObservability?.lastPathKey || "unknown", ); persistDeltaDiagnostics.reasonKey = String( persistObservability?.lastReasonKey || "graph-save", ); persistDeltaDiagnostics.pathReasonKey = String( persistObservability?.lastPathReasonKey || "unknown::graph-save", ); persistDeltaDiagnostics.pathSampleCount = Math.max( 0, Math.floor( Number( persistObservability?.byPath?.[persistDeltaDiagnostics.pathKey]?.count || 0, ), ), ); persistDeltaDiagnostics.reasonSampleCount = Math.max( 0, Math.floor( Number( persistObservability?.byReason?.[persistDeltaDiagnostics.reasonKey]?.count || 0, ), ), ); const opfsWriteLockState = typeof db?.getWriteLockSnapshot === "function" ? cloneRuntimeDebugValue(db.getWriteLockSnapshot(), null) : null; const localStoreDiagnostics = typeof readLocalStoreDiagnosticsSync === "function" ? readLocalStoreDiagnosticsSync(db, localStore) : { resolvedLocalStore: `${localStore?.storagePrimary || "indexeddb"}:${localStore?.storageMode || "indexeddb"}`, localStoreFormatVersion: localStore.storagePrimary === "opfs" ? 2 : 1, localStoreMigrationState: "idle", opfsWalDepth: 0, opfsPendingBytes: 0, opfsCompactionState: null, }; if (persistRole === "cache-mirror") { updateGraphPersistenceState({ hostProfile: persistenceEnvironment.hostProfile, primaryStorageTier: persistenceEnvironment.primaryStorageTier, cacheStorageTier: persistenceEnvironment.cacheStorageTier, cacheMirrorState: "saved", cacheLag: Math.max( 0, Number(graphPersistenceState.lukerManifestRevision || 0) - normalizeIndexedDbRevision(commitResult?.revision, requestedRevision), ), storagePrimary: localStore.storagePrimary, storageMode: localStore.storageMode, resolvedLocalStore: localStoreDiagnostics.resolvedLocalStore, localStoreFormatVersion: localStoreDiagnostics.localStoreFormatVersion, localStoreMigrationState: localStoreDiagnostics.localStoreMigrationState, indexedDbRevision: normalizeIndexedDbRevision( commitResult?.revision, requestedRevision, ), indexedDbLastError: "", lastSyncError: scheduleUploadWarning, opfsWriteLockState, opfsWalDepth: localStoreDiagnostics.opfsWalDepth, opfsPendingBytes: localStoreDiagnostics.opfsPendingBytes, opfsCompactionState: localStoreDiagnostics.opfsCompactionState, persistObservability, dualWriteLastResult: { action: "cache-mirror", target: localStore.storagePrimary, success: true, chatId: normalizedChatId, revision: normalizeIndexedDbRevision( commitResult?.revision, requestedRevision, ), reason: String(reason || "graph-save"), warning: scheduleUploadWarning || "", delta: cloneRuntimeDebugValue(commitResult?.delta, null), at: Date.now(), }, persistDelta: persistDeltaDiagnostics, }); return { saved: true, accepted: false, mirrored: true, chatId: normalizedChatId, revision: normalizeIndexedDbRevision( commitResult?.revision, requestedRevision, ), reason: String(reason || "graph-save"), saveMode: `${localStore.reasonPrefix}-cache-mirror`, storageTier: localStoreTier, warning: scheduleUploadWarning || "", delta: cloneRuntimeDebugValue(commitResult?.delta, null), snapshot, }; } updateGraphPersistenceState({ hostProfile: persistenceEnvironment.hostProfile, primaryStorageTier: persistenceEnvironment.primaryStorageTier, cacheStorageTier: persistenceEnvironment.cacheStorageTier, cacheMirrorState: persistenceEnvironment.hostProfile === "luker" ? "idle" : "none", cacheLag: persistenceEnvironment.hostProfile === "luker" ? Math.max( 0, Number(graphPersistenceState.lukerManifestRevision || 0) - normalizeIndexedDbRevision(commitResult?.revision, requestedRevision), ) : Number(graphPersistenceState.cacheLag || 0), revision: normalizeIndexedDbRevision( commitResult?.revision, requestedRevision, ), storagePrimary: localStore.storagePrimary, storageMode: localStore.storageMode, resolvedLocalStore: localStoreDiagnostics.resolvedLocalStore, localStoreFormatVersion: localStoreDiagnostics.localStoreFormatVersion, localStoreMigrationState: localStoreDiagnostics.localStoreMigrationState, dbReady: true, lastPersistedRevision: normalizeIndexedDbRevision( commitResult?.revision, requestedRevision, ), pendingPersist: false, queuedPersistRevision: 0, queuedPersistChatId: "", queuedPersistMode: "", queuedPersistRotateIntegrity: false, queuedPersistReason: "", indexedDbRevision: normalizeIndexedDbRevision( commitResult?.revision, requestedRevision, ), metadataIntegrity: getChatMetadataIntegrity(context) || currentIdentity.integrity || graphPersistenceState.metadataIntegrity, indexedDbLastError: "", lastSyncError: scheduleUploadWarning, syncDirty: true, syncDirtyReason: String(reason || "graph-save"), lastPersistReason: String(reason || "graph-save"), lastPersistMode: directPersistDelta ? `${localStore.reasonPrefix}-direct-delta` : `${localStore.reasonPrefix}-delta`, lastAcceptedRevision: Math.max( Number(graphPersistenceState.lastAcceptedRevision || 0), normalizeIndexedDbRevision(commitResult?.revision, requestedRevision), ), acceptedStorageTier: localStoreTier, acceptedBy: localStoreTier, lastRecoverableStorageTier: "none", persistDiagnosticTier: "none", opfsWriteLockState, opfsWalDepth: localStoreDiagnostics.opfsWalDepth, opfsPendingBytes: localStoreDiagnostics.opfsPendingBytes, opfsCompactionState: localStoreDiagnostics.opfsCompactionState, persistObservability, dualWriteLastResult: { action: "save", target: localStore.storagePrimary, success: true, chatId: normalizedChatId, revision: normalizeIndexedDbRevision( commitResult?.revision, requestedRevision, ), reason: String(reason || "graph-save"), warning: scheduleUploadWarning || "", delta: cloneRuntimeDebugValue(commitResult?.delta, null), at: Date.now(), }, persistDelta: persistDeltaDiagnostics, }); clearPendingGraphPersistRetry(); if ( (graphPersistenceState.loadState === GRAPH_LOAD_STATES.SHADOW_RESTORED || (graphPersistenceState.loadState === GRAPH_LOAD_STATES.LOADING && hasMeaningfulRuntimeGraphForChat(normalizedChatId, currentIdentity))) && (areChatIdsEquivalentForResolvedIdentity( normalizedChatId, graphPersistenceState.chatId || getCurrentChatId(), currentIdentity, ) || areChatIdsEquivalentForResolvedIdentity( graphPersistenceState.chatId || getCurrentChatId(), normalizedChatId, currentIdentity, )) ) { applyGraphLoadState(GRAPH_LOAD_STATES.LOADED, { chatId: normalizedChatId, reason: graphPersistenceState.loadState === GRAPH_LOAD_STATES.SHADOW_RESTORED ? `shadow-promoted:${String(reason || "graph-save")}` : `local-store-confirmed:${String(reason || "graph-save")}`, revision: normalizeIndexedDbRevision( commitResult?.revision, requestedRevision, ), lastPersistedRevision: normalizeIndexedDbRevision( commitResult?.revision, requestedRevision, ), queuedPersistRevision: 0, queuedPersistChatId: "", pendingPersist: false, shadowSnapshotUsed: true, shadowSnapshotRevision: Math.max( Number(graphPersistenceState.shadowSnapshotRevision || 0), normalizeIndexedDbRevision(commitResult?.revision, requestedRevision), ), shadowSnapshotUpdatedAt: String( graphPersistenceState.shadowSnapshotUpdatedAt || "", ), shadowSnapshotReason: String( graphPersistenceState.shadowSnapshotReason || "shadow-restore-promoted", ), dbReady: true, writesBlocked: false, }); } rememberResolvedGraphIdentityAlias(getContext(), normalizedChatId); return { saved: true, accepted: true, chatId: normalizedChatId, revision: normalizeIndexedDbRevision( commitResult?.revision, requestedRevision, ), reason: String(reason || "graph-save"), saveMode: directPersistDelta ? `${localStore.reasonPrefix}-direct-delta` : `${localStore.reasonPrefix}-delta`, storageTier: localStoreTier, warning: scheduleUploadWarning || "", delta: cloneRuntimeDebugValue(commitResult?.delta, null), snapshot, }; } catch (error) { console.warn( `[ST-BME] ${localStore.statusLabel} 写入失败,保留 metadata 兜底:`, error, ); updatePersistDeltaDiagnostics({ status: "failed", error: error?.message || String(error), failedAt: Date.now(), }); const persistenceEnvironment = buildPersistenceEnvironment(context, localStore); const opfsWriteLockState = typeof db?.getWriteLockSnapshot === "function" ? cloneRuntimeDebugValue(db.getWriteLockSnapshot(), null) : null; const localStoreDiagnostics = typeof readLocalStoreDiagnosticsSync === "function" ? readLocalStoreDiagnosticsSync(db, localStore) : { resolvedLocalStore: `${localStore?.storagePrimary || "indexeddb"}:${localStore?.storageMode || "indexeddb"}`, localStoreFormatVersion: localStore?.storagePrimary === "opfs" ? 2 : 1, localStoreMigrationState: "idle", opfsWalDepth: 0, opfsPendingBytes: 0, opfsCompactionState: null, }; updateGraphPersistenceState({ hostProfile: persistenceEnvironment.hostProfile, primaryStorageTier: persistenceEnvironment.primaryStorageTier, cacheStorageTier: persistenceEnvironment.cacheStorageTier, cacheMirrorState: persistRole === "cache-mirror" ? "error" : graphPersistenceState.cacheMirrorState, storagePrimary: localStore.storagePrimary, storageMode: localStore.storageMode, resolvedLocalStore: localStoreDiagnostics.resolvedLocalStore, localStoreFormatVersion: localStoreDiagnostics.localStoreFormatVersion, localStoreMigrationState: localStoreDiagnostics.localStoreMigrationState, indexedDbLastError: error?.message || String(error), opfsWriteLockState, opfsWalDepth: localStoreDiagnostics.opfsWalDepth, opfsPendingBytes: localStoreDiagnostics.opfsPendingBytes, opfsCompactionState: localStoreDiagnostics.opfsCompactionState, dualWriteLastResult: { action: persistRole === "cache-mirror" ? "cache-mirror" : "save", target: localStore.storagePrimary, success: false, chatId: normalizedChatId, revision: normalizeIndexedDbRevision(revision), reason: String(reason || "graph-save"), error: error?.message || String(error), at: Date.now(), }, }); return { saved: false, chatId: normalizedChatId, revision: normalizeIndexedDbRevision(revision), reason: persistRole === "cache-mirror" ? "cache-mirror-write-failed" : `${String(localStore?.reasonPrefix || "indexeddb")}-write-failed`, error, }; } } export function queueGraphPersistToIndexedDbImpl(runtime, chatId, graph, { revision = 0, reason = "graph-save", persistRole = "primary", scheduleCloudUpload = undefined, persistDelta = null, graphSnapshot = null, persistSnapshot = null, graphDetached = false, } = {}, ) { const graphPersistenceState = createGraphPersistenceStateProxy(runtime); const currentGraph = runtime.getCurrentGraph?.() || null; const nativeHydrateInstallPromiseRef = createNativeHydrateInstallPromiseRef(runtime); const nativePersistDeltaInstallPromiseRef = createNativePersistDeltaInstallPromiseRef(runtime); const bmeIndexedDbLatestQueuedRevisionByChatId = runtime.bmeIndexedDbLatestQueuedRevisionByChatId; const bmeIndexedDbWriteInFlightByChatId = runtime.bmeIndexedDbWriteInFlightByChatId; const updateGraphPersistenceState = runtime.updateGraphPersistenceState || ((patch = {}) => runtime.setGraphPersistenceState?.({ ...(runtime.getGraphPersistenceState?.() || {}), ...(patch || {}) })); const AUTHORITY_GRAPH_STORE_KIND = runtime.AUTHORITY_GRAPH_STORE_KIND; const BME_INDEXEDDB_FALLBACK_LOAD_STATE_SET = runtime.BME_INDEXEDDB_FALLBACK_LOAD_STATE_SET; const GRAPH_LOAD_STATES = runtime.GRAPH_LOAD_STATES; const applyAcceptedPendingPersistState = runtime.applyAcceptedPendingPersistState; const applyGraphLoadState = runtime.applyGraphLoadState; const applyIndexedDbEmptyToRuntime = runtime.applyIndexedDbEmptyToRuntime; const applyIndexedDbSnapshotToRuntime = runtime.applyIndexedDbSnapshotToRuntime; const applyPersistDeltaToSnapshot = runtime.applyPersistDeltaToSnapshot; const applyShadowSnapshotToRuntime = runtime.applyShadowSnapshotToRuntime; const areChatIdsEquivalentForResolvedIdentity = runtime.areChatIdsEquivalentForResolvedIdentity; const buildBmeSyncRuntimeOptions = runtime.buildBmeSyncRuntimeOptions; const buildGraphLocalStoreSelectorKey = runtime.buildGraphLocalStoreSelectorKey; const buildGraphPersistResult = runtime.buildGraphPersistResult; const buildPersistDelta = runtime.buildPersistDelta; const buildPersistDeltaFromGraphDirtyState = runtime.buildPersistDeltaFromGraphDirtyState; const buildPersistObservabilitySummary = runtime.buildPersistObservabilitySummary; const buildPersistenceEnvironment = runtime.buildPersistenceEnvironment; const buildSnapshotFromGraph = runtime.buildSnapshotFromGraph; const cacheIndexedDbSnapshot = runtime.cacheIndexedDbSnapshot; const canPersistGraphToMetadataFallback = runtime.canPersistGraphToMetadataFallback; const clearPendingGraphPersistRetry = runtime.clearPendingGraphPersistRetry; const cloneGraphForPersistence = runtime.cloneGraphForPersistence; const cloneRuntimeDebugValue = runtime.cloneRuntimeDebugValue; const createShadowComparisonGraph = runtime.createShadowComparisonGraph; const detectIndexedDbSnapshotCommitMarkerMismatch = runtime.detectIndexedDbSnapshotCommitMarkerMismatch; const detectStaleIndexedDbSnapshotAgainstRuntime = runtime.detectStaleIndexedDbSnapshotAgainstRuntime; const ensureBmeChatManager = runtime.ensureBmeChatManager; const ensureCurrentGraphRuntimeState = runtime.ensureCurrentGraphRuntimeState; const evaluateNativeHydrateGate = runtime.evaluateNativeHydrateGate; const evaluatePersistNativeDeltaGate = runtime.evaluatePersistNativeDeltaGate; const getChatMetadataIntegrity = runtime.getChatMetadataIntegrity; const getContext = runtime.getContext; const getCurrentChatId = runtime.getCurrentChatId; const getGraphPersistedRevision = runtime.getGraphPersistedRevision; const getPreferredGraphLocalStorePresentationSync = runtime.getPreferredGraphLocalStorePresentationSync; const getRequestedGraphLocalStorageMode = runtime.getRequestedGraphLocalStorageMode; const getSettings = runtime.getSettings; const hasMeaningfulRuntimeGraphForChat = runtime.hasMeaningfulRuntimeGraphForChat; const isAuthorityGraphStorePresentation = runtime.isAuthorityGraphStorePresentation; const isGraphLocalStorageModeOpfs = runtime.isGraphLocalStorageModeOpfs; const isIndexedDbSnapshotMeaningful = runtime.isIndexedDbSnapshotMeaningful; const isRestoreLockActive = runtime.isRestoreLockActive; const maybeCaptureGraphShadowSnapshot = runtime.maybeCaptureGraphShadowSnapshot; const maybeClearAcceptedPendingPersistState = runtime.maybeClearAcceptedPendingPersistState; const maybeImportLegacyIndexedDbSnapshotToLocalStore = runtime.maybeImportLegacyIndexedDbSnapshotToLocalStore; const maybeImportLegacyOpfsSnapshotToLocalStore = runtime.maybeImportLegacyOpfsSnapshotToLocalStore; const maybeMigrateLegacyGraphToIndexedDb = runtime.maybeMigrateLegacyGraphToIndexedDb; const maybeRecoverIndexedDbGraphFromStableIdentity = runtime.maybeRecoverIndexedDbGraphFromStableIdentity; const maybeResolveOrphanAcceptedCommitMarker = runtime.maybeResolveOrphanAcceptedCommitMarker; const maybeResumePendingAutoExtraction = runtime.maybeResumePendingAutoExtraction; const normalizeChatIdCandidate = runtime.normalizeChatIdCandidate; const normalizeGraphRuntimeState = runtime.normalizeGraphRuntimeState; const normalizeIndexedDbRevision = runtime.normalizeIndexedDbRevision; const normalizeLoadDiagnosticsMs = runtime.normalizeLoadDiagnosticsMs; const normalizePersistDeltaDiagnosticsMs = runtime.normalizePersistDeltaDiagnosticsMs; const persistGraphToChatMetadata = runtime.persistGraphToChatMetadata; const persistGraphToConfiguredDurableTier = runtime.persistGraphToConfiguredDurableTier; const pruneGraphPersistDirtyState = runtime.pruneGraphPersistDirtyState; const queueGraphPersist = runtime.queueGraphPersist; const queueRuntimeGraphLocalStoreRepair = runtime.queueRuntimeGraphLocalStoreRepair; const readCachedIndexedDbSnapshot = runtime.readCachedIndexedDbSnapshot; const readLoadDiagnosticsNow = runtime.readLoadDiagnosticsNow; const readLocalStoreDiagnosticsSync = runtime.readLocalStoreDiagnosticsSync; const readPersistDeltaDiagnosticsNow = runtime.readPersistDeltaDiagnosticsNow; const recordLocalPersistEarlyFailure = runtime.recordLocalPersistEarlyFailure; const recordPersistMismatchDiagnostic = runtime.recordPersistMismatchDiagnostic; const refreshCurrentChatLocalStoreBinding = runtime.refreshCurrentChatLocalStoreBinding; const rememberResolvedGraphIdentityAlias = runtime.rememberResolvedGraphIdentityAlias; const resolveCompatibleGraphShadowSnapshot = runtime.resolveCompatibleGraphShadowSnapshot; const resolveCurrentChatIdentity = runtime.resolveCurrentChatIdentity; const resolveDbGraphStorePresentation = runtime.resolveDbGraphStorePresentation; const resolveLocalStoreTierFromPresentation = runtime.resolveLocalStoreTierFromPresentation; const resolvePendingPersistGraphSource = runtime.resolvePendingPersistGraphSource; const resolvePendingPersistLastProcessedAssistantFloor = runtime.resolvePendingPersistLastProcessedAssistantFloor; const resolvePersistRevisionFloor = runtime.resolvePersistRevisionFloor; const resolveSnapshotGraphStorePresentation = runtime.resolveSnapshotGraphStorePresentation; const schedulePendingGraphPersistRetry = runtime.schedulePendingGraphPersistRetry; const scheduleUpload = runtime.scheduleUpload; const shouldPreferShadowSnapshotOverOfficial = runtime.shouldPreferShadowSnapshotOverOfficial; const stampGraphPersistenceMeta = runtime.stampGraphPersistenceMeta; const syncCommitMarkerToPersistenceState = runtime.syncCommitMarkerToPersistenceState; const updateLoadDiagnostics = runtime.updateLoadDiagnostics; const updatePersistDeltaDiagnostics = runtime.updatePersistDeltaDiagnostics; const console = runtime.console || globalThis.console; const normalizedChatId = normalizeChatIdCandidate(chatId); if (!normalizedChatId || (!graph && !persistDelta)) return; if (persistRole === "cache-mirror") { const persistenceEnvironment = buildPersistenceEnvironment( getContext(), getPreferredGraphLocalStorePresentationSync(), ); updateGraphPersistenceState({ hostProfile: persistenceEnvironment.hostProfile, primaryStorageTier: persistenceEnvironment.primaryStorageTier, cacheStorageTier: persistenceEnvironment.cacheStorageTier, cacheMirrorState: "queued", }); } const normalizedRevision = normalizeIndexedDbRevision(revision); const latestQueuedRevision = normalizeIndexedDbRevision( bmeIndexedDbLatestQueuedRevisionByChatId.get(normalizedChatId), ); bmeIndexedDbLatestQueuedRevisionByChatId.set( normalizedChatId, Math.max(latestQueuedRevision, normalizedRevision), ); const previousWritePromise = bmeIndexedDbWriteInFlightByChatId.get(normalizedChatId) || Promise.resolve(); const nextWritePromise = previousWritePromise .catch(() => null) .then(async () => { const currentLatestRevision = normalizeIndexedDbRevision( bmeIndexedDbLatestQueuedRevisionByChatId.get(normalizedChatId), ); if ( normalizedRevision > 0 && normalizedRevision < currentLatestRevision ) { return { saved: false, skipped: true, reason: "indexeddb-write-superseded", revision: normalizedRevision, }; } const persistGraphSnapshot = graphSnapshot ? graphSnapshot : graph ? graphDetached === true ? normalizeGraphRuntimeState(graph, normalizedChatId) : cloneGraphForPersistence(graph, normalizedChatId) : null; return await saveGraphToIndexedDbImpl(runtime, normalizedChatId, persistGraphSnapshot, { revision: normalizedRevision, reason, persistRole, scheduleCloudUpload, persistDelta, graphSnapshot: persistGraphSnapshot, persistSnapshot, sourceGraph: graphDetached === true ? null : graph, }); }) .finally(() => { if ( bmeIndexedDbWriteInFlightByChatId.get(normalizedChatId) === nextWritePromise ) { bmeIndexedDbWriteInFlightByChatId.delete(normalizedChatId); } }); bmeIndexedDbWriteInFlightByChatId.set(normalizedChatId, nextWritePromise); }