Skip to content

Commit dec9c98

Browse files
fix(seer-explorer): Simplify optimistic UI clearing logic
Remove baselineSignature comparison and timeout in favor of directly checking whether the server has the expected user block at the insert index with matching content, then whether an assistant block follows.
1 parent aeb4725 commit dec9c98

File tree

1 file changed

+15
-48
lines changed

1 file changed

+15
-48
lines changed

static/app/views/seerExplorer/hooks/useSeerExplorer.tsx

Lines changed: 15 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,6 @@ export const useSeerExplorer = () => {
148148
const [optimistic, setOptimistic] = useState<{
149149
assistantBlockId: string;
150150
assistantContent: string;
151-
baselineSignature: string;
152-
createdAt: number;
153151
insertIndex: number;
154152
userBlockId: string;
155153
userQuery: string;
@@ -210,16 +208,6 @@ export const useSeerExplorer = () => {
210208
deletedFromIndex ?? (apiData?.session?.blocks.length || 0);
211209
const calculatedInsertIndex = insertIndex ?? effectiveMessageLength;
212210

213-
// Record current real blocks signature to know when to clear optimistic UI
214-
const baselineSignature = JSON.stringify(
215-
(apiData?.session?.blocks || []).map(b => [
216-
b.id,
217-
b.message.role,
218-
b.message.content,
219-
!!b.loading,
220-
])
221-
);
222-
223211
// Generate deterministic block IDs matching backend logic
224212
// Backend generates: `{prefix}-{index}-{content[:16].replace(' ', '-')}`
225213
const generateBlockId = (prefix: string, content: string, index: number) => {
@@ -236,8 +224,6 @@ export const useSeerExplorer = () => {
236224
setOptimistic({
237225
insertIndex: calculatedInsertIndex,
238226
userQuery: query,
239-
baselineSignature,
240-
createdAt: Date.now(),
241227
userBlockId: generateBlockId('user', query, calculatedInsertIndex),
242228
assistantBlockId: generateBlockId(
243229
'loading',
@@ -457,53 +443,34 @@ export const useSeerExplorer = () => {
457443
return sessionData;
458444
}, [sessionData, deletedFromIndex, optimistic, runId]);
459445

460-
// Clear optimistic blocks once the server has a real assistant response.
461-
// The server acknowledges the user message before the Celery worker produces
462-
// an assistant block, so we keep the optimistic "Thinking" block visible
463-
// until a real assistant block appears after the insert point (or a 30s timeout).
446+
// Clear optimistic blocks once the server has persisted the user message
447+
// and produced a real assistant response after the insert point.
464448
useEffect(() => {
465449
if (!optimistic) {
466450
return undefined;
467451
}
468452

469-
const isTimedOut = Date.now() - optimistic.createdAt > 30_000;
453+
const serverBlocks = apiData?.session?.blocks || [];
454+
const blockAtInsert = serverBlocks[optimistic.insertIndex];
470455

471-
if (isTimedOut) {
472-
setOptimistic(null);
473-
setDeletedFromIndex(null);
456+
const serverHasUserBlock =
457+
blockAtInsert?.message.role === 'user' &&
458+
blockAtInsert?.message.content === optimistic.userQuery;
459+
460+
if (!serverHasUserBlock) {
474461
return undefined;
475462
}
476463

477-
const currentSignature = JSON.stringify(
478-
(apiData?.session?.blocks || []).map(b => [
479-
b.id,
480-
b.message.role,
481-
b.message.content,
482-
!!b.loading,
483-
])
464+
const hasAssistantResponse = serverBlocks.some(
465+
(b, i) => i > optimistic.insertIndex && b.message.role === 'assistant'
484466
);
485467

486-
if (currentSignature !== optimistic.baselineSignature) {
487-
const serverBlocks = apiData?.session?.blocks || [];
488-
const hasAssistantResponse = serverBlocks.some(
489-
(b, i) => i >= optimistic.insertIndex && b.message.role === 'assistant'
490-
);
491-
492-
if (hasAssistantResponse) {
493-
setOptimistic(null);
494-
setDeletedFromIndex(null);
495-
return undefined;
496-
}
497-
}
498-
499-
// Always schedule the safety timeout so the optimistic UI cannot persist
500-
// indefinitely when the server data signature never diverges from baseline.
501-
const remaining = 30_000 - (Date.now() - optimistic.createdAt);
502-
const timer = setTimeout(() => {
468+
if (hasAssistantResponse) {
503469
setOptimistic(null);
504470
setDeletedFromIndex(null);
505-
}, remaining);
506-
return () => clearTimeout(timer);
471+
}
472+
473+
return undefined;
507474
}, [apiData?.session?.blocks, optimistic]);
508475

509476
// Detect PR creation errors and show error messages

0 commit comments

Comments
 (0)