fix(coding): keep optimistic identity across snapshots

This commit is contained in:
2026-08-23 22:39:34 +08:00
parent 1abb2fff36
commit 934ba02718
3 changed files with 77 additions and 9 deletions

View File

@@ -160,6 +160,22 @@ function withoutReconciledRequests(
);
}
function withReconciledOptimisticNodeIds(
snapshot: ConversationSnapshot,
requests: Record<string, CodingPromptRequestState> | undefined,
): ConversationSnapshot {
if (!requests) return snapshot;
let changed = false;
const nodes = snapshot.nodes.map((node) => {
if (node.kind !== 'message' || !node.clientRequestId) return node;
const nodeId = requests[node.clientRequestId]?.nodeId;
if (!nodeId || node.id === nodeId) return node;
changed = true;
return { ...node, id: nodeId };
});
return changed ? { ...snapshot, nodes } : snapshot;
}
function optimisticNode(
nodeId: string,
clientRequestId: string,
@@ -601,12 +617,16 @@ export function createCodingConversationStore(
if (!current.reducer.invalidation && snapshotIsOlder(current.reducer.snapshot, snapshot)) {
return state;
}
const reconciledSnapshot = withReconciledOptimisticNodeIds(
snapshot,
state.requestsByConversationId[event.conversationId],
);
const requests = withoutReconciledRequests(
state.requestsByConversationId[event.conversationId],
snapshot,
reconciledSnapshot,
);
const reducer = withUnreconciledOptimisticNodes(
replaceConversationSnapshot(current.reducer, snapshot),
replaceConversationSnapshot(current.reducer, reconciledSnapshot),
requests,
);
const entry: CodingConversationEntry = {