refactor(sync): extract saveGraphToChat + luker cache action (Phase 5e)

This commit is contained in:
youzini
2026-05-31 13:22:49 +00:00
parent 0160a0da83
commit 23318ea0dc
3 changed files with 357 additions and 237 deletions

251
index.js
View File

@@ -354,7 +354,9 @@ import {
buildBmeSyncRuntimeOptionsImpl,
loadGraphFromChatImpl,
maybeCaptureGraphShadowSnapshotImpl,
onRebuildLocalCacheFromLukerSidecarImpl,
persistExtractionBatchResultImpl,
saveGraphToChatImpl,
shouldUseAuthorityGraphStoreImpl,
shouldUseAuthorityJobsImpl,
syncGraphLoadFromLiveContextImpl,
@@ -1392,9 +1394,14 @@ function createGraphLoadPersistRuntime() {
isAuthorityJobTypeSupported,
isAuthorityVectorConfig,
isGraphEffectivelyEmpty,
isGraphLoadStateDbReady,
isGraphMetadataWriteAllowed,
isIndexedDbSnapshotMeaningful,
isLukerPrimaryPersistenceHost,
loadGraphFromLukerSidecarV2,
loadGraphFromChat,
loadGraphFromIndexedDb,
normalizeIndexedDbRevision,
normalizeAuthorityCapabilityState,
normalizeAuthorityJobConfig,
normalizeAuthoritySettings,
@@ -1403,6 +1410,7 @@ function createGraphLoadPersistRuntime() {
persistGraphToChatMetadata,
persistGraphToConfiguredDurableTier,
queueGraphPersist,
queueGraphPersistToIndexedDb,
readCachedIndexedDbSnapshot,
recordLocalPersistEarlyFailure,
recordAuthorityBlobSnapshot,
@@ -1412,11 +1420,14 @@ function createGraphLoadPersistRuntime() {
rememberResolvedGraphIdentityAlias,
resolveCompatibleGraphShadowSnapshot,
resolveCurrentChatIdentity,
resolveCurrentChatStateTarget,
resolvePersistRevisionFloor,
resolvePersistenceChatId,
resolvePreferredGraphLocalStorePresentation,
resolveSnapshotGraphStorePresentation,
restoreRecallUiStateFromPersistence,
runAuthorityConsistencyAudit,
scheduleBmeIndexedDbTask,
scheduleGraphChatStateProbe,
scheduleIndexedDbGraphProbe,
schedulePersistedRecallMessageUiRefresh,
@@ -1427,6 +1438,7 @@ function createGraphLoadPersistRuntime() {
stampGraphPersistenceMeta,
syncCommitMarkerToPersistenceState,
updateGraphPersistenceState,
toastr,
writeAuthorityLukerCheckpointBlob,
writeGraphShadowSnapshot,
};
@@ -14505,205 +14517,7 @@ function queueGraphPersistToIndexedDb(
}
function saveGraphToChat(options = {}) {
const context = getContext();
if (!context || !currentGraph) {
return buildGraphPersistResult({
saved: false,
blocked: true,
reason: "missing-context-or-graph",
});
}
const chatId = resolvePersistenceChatId(context, currentGraph);
const {
reason = "graph-save",
markMutation = true,
persistMetadata = false,
captureShadow = Boolean(persistMetadata),
immediate = markMutation,
} = options;
ensureCurrentGraphRuntimeState();
currentGraph.historyState.extractionCount = extractionCount;
if (!chatId) {
recordLocalPersistEarlyFailure("missing-chat-id", {
chatId,
revision: 0,
});
return buildGraphPersistResult({
saved: false,
blocked: true,
reason: "missing-chat-id",
});
}
const revision = markMutation
? allocateRequestedPersistRevision(0, currentGraph)
: resolvePersistRevisionFloor(0, currentGraph);
const persistenceEnvironment = buildPersistenceEnvironment(
context,
getPreferredGraphLocalStorePresentationSync(),
);
if (captureShadow) {
maybeCaptureGraphShadowSnapshot(reason);
}
const shouldQueueIndexedDbPersist =
(persistenceEnvironment.hostProfile !== "luker" ||
persistenceEnvironment.primaryStorageTier === "authority-sql") &&
(markMutation || !isGraphEffectivelyEmpty(currentGraph));
if (shouldQueueIndexedDbPersist) {
queueGraphPersistToIndexedDb(chatId, currentGraph, {
revision,
reason,
});
}
const metadataFallbackEnabled =
Boolean(persistMetadata) || !ensureBmeChatManager();
if (!markMutation) {
const hasMeaningfulGraphData = !isGraphEffectivelyEmpty(currentGraph);
if (
!hasMeaningfulGraphData ||
graphPersistenceState.loadState === GRAPH_LOAD_STATES.EMPTY_CONFIRMED
) {
return buildGraphPersistResult({
saved: false,
blocked: false,
reason: hasMeaningfulGraphData
? "passive-empty-confirmed-skipped"
: "passive-empty-graph-skipped",
revision,
});
}
}
if (persistenceEnvironment.primaryStorageTier === "luker-chat-state") {
const persistGraph = cloneGraphForPersistence(currentGraph, chatId);
const chatStateTarget = resolveCurrentChatStateTarget(context);
const lastProcessedAssistantFloor = Number.isFinite(
Number(persistGraph?.historyState?.lastProcessedAssistantFloor),
)
? Number(persistGraph.historyState.lastProcessedAssistantFloor)
: null;
scheduleBmeIndexedDbTask(async () => {
const persistResult = await persistGraphToConfiguredDurableTier(
context,
persistGraph,
{
chatId,
revision,
reason,
lastProcessedAssistantFloor,
chatStateTarget,
graphDetached: true,
},
);
if (!persistResult?.accepted) {
queueGraphPersist(reason, revision, {
immediate,
graph: persistGraph,
chatId,
captureShadow,
});
}
refreshPanelLiveState();
});
updateGraphPersistenceState({
hostProfile: persistenceEnvironment.hostProfile,
primaryStorageTier: persistenceEnvironment.primaryStorageTier,
cacheStorageTier: persistenceEnvironment.cacheStorageTier,
lastPersistReason: String(reason || "graph-save"),
lastPersistMode: "luker-chat-state-queued",
});
return buildGraphPersistResult({
saved: false,
queued: true,
blocked: false,
accepted: false,
reason: "luker-chat-state-queued",
revision,
saveMode: "luker-chat-state-queued",
storageTier: "luker-chat-state",
primaryTier: persistenceEnvironment.primaryStorageTier,
cacheTier: persistenceEnvironment.cacheStorageTier,
});
}
if (!metadataFallbackEnabled) {
const preferredLocalStore = getPreferredGraphLocalStorePresentationSync();
const saveMode = shouldQueueIndexedDbPersist
? `${preferredLocalStore.reasonPrefix}-queued`
: `${preferredLocalStore.reasonPrefix}-skip`;
updateGraphPersistenceState({
storagePrimary: preferredLocalStore.storagePrimary,
storageMode: preferredLocalStore.storageMode,
dbReady:
graphPersistenceState.dbReady ??
isGraphLoadStateDbReady(graphPersistenceState.loadState),
lastPersistReason: String(reason || "graph-save"),
lastPersistMode: saveMode,
pendingPersist: false,
queuedPersistChatId: "",
queuedPersistMode: "",
queuedPersistReason: "",
queuedPersistRotateIntegrity: false,
dualWriteLastResult: {
action: "save",
target: preferredLocalStore.storagePrimary,
queued: Boolean(shouldQueueIndexedDbPersist),
success: true,
chatId,
revision: normalizeIndexedDbRevision(revision),
reason: String(reason || "graph-save"),
at: Date.now(),
},
});
return buildGraphPersistResult({
saved: false,
queued: Boolean(shouldQueueIndexedDbPersist),
blocked: false,
accepted: false,
reason: shouldQueueIndexedDbPersist
? `${preferredLocalStore.reasonPrefix}-queued`
: `${preferredLocalStore.reasonPrefix}-empty-skip`,
revision,
saveMode,
storageTier: shouldQueueIndexedDbPersist
? preferredLocalStore.storagePrimary
: "none",
});
}
if (!isGraphMetadataWriteAllowed()) {
console.warn(
`[ST-BME] 图谱写回已被安全保护拦截chat=${chatId}state=${graphPersistenceState.loadState}reason=${reason}`,
);
return queueGraphPersist(reason, revision, { immediate });
}
const metadataPersistResult = persistGraphToChatMetadata(context, {
reason,
revision,
immediate,
});
updateGraphPersistenceState({
storageMode: "metadata-full",
dualWriteLastResult: {
action: "save",
target: "metadata",
success: Boolean(metadataPersistResult?.saved),
queued: Boolean(metadataPersistResult?.queued),
blocked: Boolean(metadataPersistResult?.blocked),
chatId,
revision: normalizeIndexedDbRevision(revision),
reason: String(reason || "graph-save"),
at: Date.now(),
},
});
return metadataPersistResult;
return saveGraphToChatImpl(createGraphLoadPersistRuntime(), options);
}
function handleGraphShadowSnapshotPageHide() {
@@ -17677,44 +17491,7 @@ async function onProbeGraphLoad() {
}
async function onRebuildLocalCacheFromLukerSidecar() {
const context = getContext();
const chatStateTarget = resolveCurrentChatStateTarget(context);
if (!isLukerPrimaryPersistenceHost(context)) {
toastr.info("当前宿主不是 Luker无需从主 sidecar 重建本地缓存");
return { handledToast: true, reason: "not-luker" };
}
const chatId = getCurrentChatId(context);
if (!chatId) {
toastr.warning("当前没有聊天上下文");
return { handledToast: true, reason: "missing-chat-id" };
}
const loadResult = await loadGraphFromLukerSidecarV2(chatId, {
source: "panel-manual-luker-cache-rebuild",
allowOverride: true,
chatStateTarget,
});
if (!loadResult?.loaded || !currentGraph) {
toastr.warning(
`无法从 Luker 主 sidecar 重建本地缓存: ${loadResult?.reason || "sidecar not available"}`,
);
return { handledToast: true, result: loadResult };
}
queueGraphPersistToIndexedDb(chatId, cloneGraphForPersistence(currentGraph, chatId), {
revision: Math.max(
Number(graphPersistenceState.lukerManifestRevision || 0),
Number(getGraphPersistedRevision(currentGraph) || 0),
Number(graphPersistenceState.revision || 0),
),
reason: "panel-manual-luker-cache-rebuild",
persistRole: "cache-mirror",
scheduleCloudUpload: false,
graphDetached: true,
});
refreshPanelLiveState();
toastr.success("已开始从 Luker 主 sidecar 重建本地缓存");
return { handledToast: true, result: loadResult };
return await onRebuildLocalCacheFromLukerSidecarImpl(createGraphLoadPersistRuntime());
}
async function onRepairLukerSidecar() {

View File

@@ -1838,3 +1838,309 @@ export function loadGraphFromChatImpl(runtime, options = {}) {
};
}
export function saveGraphToChatImpl(runtime, options = {}) {
const graphPersistenceState = new Proxy({}, {
get(_target, key) {
return (runtime.getGraphPersistenceState?.() || {})[key];
},
set(_target, key, value) {
const state = runtime.getGraphPersistenceState?.() || {};
state[key] = value;
return true;
},
});
let currentGraph = runtime.getCurrentGraph?.() || null;
const GRAPH_LOAD_STATES = runtime.GRAPH_LOAD_STATES;
const allocateRequestedPersistRevision = runtime.allocateRequestedPersistRevision;
const buildGraphPersistResult = runtime.buildGraphPersistResult;
const buildPersistenceEnvironment = runtime.buildPersistenceEnvironment;
const canPersistGraphToMetadataFallback = runtime.canPersistGraphToMetadataFallback;
const cloneGraphForPersistence = runtime.cloneGraphForPersistence;
const ensureBmeChatManager = runtime.ensureBmeChatManager;
const ensureCurrentGraphRuntimeState = runtime.ensureCurrentGraphRuntimeState;
const getContext = runtime.getContext;
const getGraphPersistedRevision = runtime.getGraphPersistedRevision;
const getPreferredGraphLocalStorePresentationSync = runtime.getPreferredGraphLocalStorePresentationSync;
const isGraphEffectivelyEmpty = runtime.isGraphEffectivelyEmpty;
const isGraphLoadStateDbReady = runtime.isGraphLoadStateDbReady;
const isGraphMetadataWriteAllowed = runtime.isGraphMetadataWriteAllowed;
const normalizeIndexedDbRevision = runtime.normalizeIndexedDbRevision;
const persistGraphToChatMetadata = runtime.persistGraphToChatMetadata;
const persistGraphToConfiguredDurableTier = runtime.persistGraphToConfiguredDurableTier;
const queueGraphPersist = runtime.queueGraphPersist;
const queueGraphPersistToIndexedDb = runtime.queueGraphPersistToIndexedDb;
const recordLocalPersistEarlyFailure = runtime.recordLocalPersistEarlyFailure;
const refreshPanelLiveState = runtime.refreshPanelLiveState;
const resolveCurrentChatStateTarget = runtime.resolveCurrentChatStateTarget;
const resolvePersistRevisionFloor = runtime.resolvePersistRevisionFloor;
const resolvePersistenceChatId = runtime.resolvePersistenceChatId;
const scheduleBmeIndexedDbTask = runtime.scheduleBmeIndexedDbTask;
const updateGraphPersistenceState = runtime.updateGraphPersistenceState;
const console = runtime.console || globalThis.console;
const context = getContext();
if (!context || !currentGraph) {
return buildGraphPersistResult({
saved: false,
blocked: true,
reason: "missing-context-or-graph",
});
}
const chatId = resolvePersistenceChatId(context, currentGraph);
const {
reason = "graph-save",
markMutation = true,
persistMetadata = false,
captureShadow = Boolean(persistMetadata),
immediate = markMutation,
} = options;
ensureCurrentGraphRuntimeState();
currentGraph = runtime.getCurrentGraph?.() || null;
currentGraph.historyState.extractionCount = runtime.getExtractionCount?.() || 0;
if (!chatId) {
recordLocalPersistEarlyFailure("missing-chat-id", {
chatId,
revision: 0,
});
return buildGraphPersistResult({
saved: false,
blocked: true,
reason: "missing-chat-id",
});
}
const revision = markMutation
? allocateRequestedPersistRevision(0, currentGraph)
: resolvePersistRevisionFloor(0, currentGraph);
const persistenceEnvironment = buildPersistenceEnvironment(
context,
getPreferredGraphLocalStorePresentationSync(),
);
if (captureShadow) {
maybeCaptureGraphShadowSnapshotImpl(runtime, reason);
}
const shouldQueueIndexedDbPersist =
(persistenceEnvironment.hostProfile !== "luker" ||
persistenceEnvironment.primaryStorageTier === "authority-sql") &&
(markMutation || !isGraphEffectivelyEmpty(currentGraph));
if (shouldQueueIndexedDbPersist) {
queueGraphPersistToIndexedDb(chatId, currentGraph, {
revision,
reason,
});
}
const metadataFallbackEnabled =
Boolean(persistMetadata) || !ensureBmeChatManager();
if (!markMutation) {
const hasMeaningfulGraphData = !isGraphEffectivelyEmpty(currentGraph);
if (
!hasMeaningfulGraphData ||
graphPersistenceState.loadState === GRAPH_LOAD_STATES.EMPTY_CONFIRMED
) {
return buildGraphPersistResult({
saved: false,
blocked: false,
reason: hasMeaningfulGraphData
? "passive-empty-confirmed-skipped"
: "passive-empty-graph-skipped",
revision,
});
}
}
if (persistenceEnvironment.primaryStorageTier === "luker-chat-state") {
const persistGraph = cloneGraphForPersistence(currentGraph, chatId);
const chatStateTarget = resolveCurrentChatStateTarget(context);
const lastProcessedAssistantFloor = Number.isFinite(
Number(persistGraph?.historyState?.lastProcessedAssistantFloor),
)
? Number(persistGraph.historyState.lastProcessedAssistantFloor)
: null;
scheduleBmeIndexedDbTask(async () => {
const persistResult = await persistGraphToConfiguredDurableTier(
context,
persistGraph,
{
chatId,
revision,
reason,
lastProcessedAssistantFloor,
chatStateTarget,
graphDetached: true,
},
);
if (!persistResult?.accepted) {
queueGraphPersist(reason, revision, {
immediate,
graph: persistGraph,
chatId,
captureShadow,
});
}
refreshPanelLiveState();
});
updateGraphPersistenceState({
hostProfile: persistenceEnvironment.hostProfile,
primaryStorageTier: persistenceEnvironment.primaryStorageTier,
cacheStorageTier: persistenceEnvironment.cacheStorageTier,
lastPersistReason: String(reason || "graph-save"),
lastPersistMode: "luker-chat-state-queued",
});
return buildGraphPersistResult({
saved: false,
queued: true,
blocked: false,
accepted: false,
reason: "luker-chat-state-queued",
revision,
saveMode: "luker-chat-state-queued",
storageTier: "luker-chat-state",
primaryTier: persistenceEnvironment.primaryStorageTier,
cacheTier: persistenceEnvironment.cacheStorageTier,
});
}
if (!metadataFallbackEnabled) {
const preferredLocalStore = getPreferredGraphLocalStorePresentationSync();
const saveMode = shouldQueueIndexedDbPersist
? `${preferredLocalStore.reasonPrefix}-queued`
: `${preferredLocalStore.reasonPrefix}-skip`;
updateGraphPersistenceState({
storagePrimary: preferredLocalStore.storagePrimary,
storageMode: preferredLocalStore.storageMode,
dbReady:
graphPersistenceState.dbReady ??
isGraphLoadStateDbReady(graphPersistenceState.loadState),
lastPersistReason: String(reason || "graph-save"),
lastPersistMode: saveMode,
pendingPersist: false,
queuedPersistChatId: "",
queuedPersistMode: "",
queuedPersistReason: "",
queuedPersistRotateIntegrity: false,
dualWriteLastResult: {
action: "save",
target: preferredLocalStore.storagePrimary,
queued: Boolean(shouldQueueIndexedDbPersist),
success: true,
chatId,
revision: normalizeIndexedDbRevision(revision),
reason: String(reason || "graph-save"),
at: Date.now(),
},
});
return buildGraphPersistResult({
saved: false,
queued: Boolean(shouldQueueIndexedDbPersist),
blocked: false,
accepted: false,
reason: shouldQueueIndexedDbPersist
? `${preferredLocalStore.reasonPrefix}-queued`
: `${preferredLocalStore.reasonPrefix}-empty-skip`,
revision,
saveMode,
storageTier: shouldQueueIndexedDbPersist
? preferredLocalStore.storagePrimary
: "none",
});
}
if (!isGraphMetadataWriteAllowed()) {
console.warn(
`[ST-BME] 图谱写回已被安全保护拦截chat=${chatId}state=${graphPersistenceState.loadState}reason=${reason}`,
);
return queueGraphPersist(reason, revision, { immediate });
}
const metadataPersistResult = persistGraphToChatMetadata(context, {
reason,
revision,
immediate,
});
updateGraphPersistenceState({
storageMode: "metadata-full",
dualWriteLastResult: {
action: "save",
target: "metadata",
success: Boolean(metadataPersistResult?.saved),
queued: Boolean(metadataPersistResult?.queued),
blocked: Boolean(metadataPersistResult?.blocked),
chatId,
revision: normalizeIndexedDbRevision(revision),
reason: String(reason || "graph-save"),
at: Date.now(),
},
});
return metadataPersistResult;
}
export async function onRebuildLocalCacheFromLukerSidecarImpl(runtime) {
const graphPersistenceState = new Proxy({}, {
get(_target, key) {
return (runtime.getGraphPersistenceState?.() || {})[key];
},
set(_target, key, value) {
const state = runtime.getGraphPersistenceState?.() || {};
state[key] = value;
return true;
},
});
let currentGraph = runtime.getCurrentGraph?.() || null;
const cloneGraphForPersistence = runtime.cloneGraphForPersistence;
const getContext = runtime.getContext;
const getCurrentChatId = runtime.getCurrentChatId;
const getGraphPersistedRevision = runtime.getGraphPersistedRevision;
const isLukerPrimaryPersistenceHost = runtime.isLukerPrimaryPersistenceHost;
const loadGraphFromLukerSidecarV2 = runtime.loadGraphFromLukerSidecarV2;
const queueGraphPersistToIndexedDb = runtime.queueGraphPersistToIndexedDb;
const refreshPanelLiveState = runtime.refreshPanelLiveState;
const resolveCurrentChatStateTarget = runtime.resolveCurrentChatStateTarget;
const toastr = runtime.toastr;
const context = getContext();
const chatStateTarget = resolveCurrentChatStateTarget(context);
if (!isLukerPrimaryPersistenceHost(context)) {
toastr.info("当前宿主不是 Luker无需从主 sidecar 重建本地缓存");
return { handledToast: true, reason: "not-luker" };
}
const chatId = getCurrentChatId(context);
if (!chatId) {
toastr.warning("当前没有聊天上下文");
return { handledToast: true, reason: "missing-chat-id" };
}
const loadResult = await loadGraphFromLukerSidecarV2(chatId, {
source: "panel-manual-luker-cache-rebuild",
allowOverride: true,
chatStateTarget,
});
currentGraph = runtime.getCurrentGraph?.() || null;
if (!loadResult?.loaded || !currentGraph) {
toastr.warning(
`无法从 Luker 主 sidecar 重建本地缓存: ${loadResult?.reason || "sidecar not available"}`,
);
return { handledToast: true, result: loadResult };
}
queueGraphPersistToIndexedDb(chatId, cloneGraphForPersistence(currentGraph, chatId), {
revision: Math.max(
Number(graphPersistenceState.lukerManifestRevision || 0),
Number(getGraphPersistedRevision(currentGraph) || 0),
Number(graphPersistenceState.revision || 0),
),
reason: "panel-manual-luker-cache-rebuild",
persistRole: "cache-mirror",
scheduleCloudUpload: false,
graphDetached: true,
});
refreshPanelLiveState();
toastr.success("已开始从 Luker 主 sidecar 重建本地缓存");
return { handledToast: true, result: loadResult };
}

View File

@@ -192,7 +192,9 @@ import {
buildBmeSyncRuntimeOptionsImpl,
loadGraphFromChatImpl,
maybeCaptureGraphShadowSnapshotImpl,
onRebuildLocalCacheFromLukerSidecarImpl,
persistExtractionBatchResultImpl,
saveGraphToChatImpl,
shouldUseAuthorityGraphStoreImpl,
shouldUseAuthorityJobsImpl,
syncGraphLoadFromLiveContextImpl,
@@ -860,7 +862,9 @@ async function createGraphPersistenceHarness({
buildBmeSyncRuntimeOptionsImpl,
loadGraphFromChatImpl,
maybeCaptureGraphShadowSnapshotImpl,
onRebuildLocalCacheFromLukerSidecarImpl,
persistExtractionBatchResultImpl,
saveGraphToChatImpl,
shouldUseAuthorityGraphStoreImpl,
shouldUseAuthorityJobsImpl,
syncGraphLoadFromLiveContextImpl,
@@ -1368,6 +1372,39 @@ async function createGraphPersistenceHarness({
recordLocalPersistEarlyFailure(reason = "") {
runtimeContext.__lastLocalPersistEarlyFailure = String(reason || "");
},
isGraphLoadStateDbReady(loadState = runtimeContext.graphPersistenceState?.loadState) {
return loadState === GRAPH_LOAD_STATES.LOADED || loadState === GRAPH_LOAD_STATES.EMPTY_CONFIRMED;
},
isGraphMetadataWriteAllowed() {
return true;
},
isLukerPrimaryPersistenceHost(context = runtimeContext.getContext?.()) {
return resolveBmeHostProfile(context) === "luker";
},
async loadGraphFromLukerSidecarV2(chatId, options = {}) {
runtimeContext.__lastLukerSidecarLoad = { chatId, options };
return { loaded: Boolean(runtimeContext.currentGraph), reason: "test-luker-sidecar" };
},
normalizeIndexedDbRevision(value, fallbackValue = 0) {
const numeric = Number(value);
if (Number.isFinite(numeric) && numeric > 0) return Math.floor(numeric);
const fallback = Number(fallbackValue);
return Number.isFinite(fallback) && fallback > 0 ? Math.floor(fallback) : 0;
},
resolvePersistRevisionFloor(baseRevision = 0, graph = runtimeContext.currentGraph) {
return Math.max(
0,
Math.floor(Number(baseRevision || 0)),
Math.floor(Number(graph?.meta?.revision || 0)),
Math.floor(Number(getGraphPersistedRevision(graph) || 0)),
);
},
resolveCurrentChatStateTarget(context = runtimeContext.getContext?.()) {
return resolveCurrentBmeChatStateTarget(context);
},
scheduleBmeIndexedDbTask(task) {
return Promise.resolve().then(() => task());
},
__syncNowCalls: [],
async syncNow(chatId, options = {}) {
runtimeContext.__syncNowCalls.push({