fix: align pending questions by native occurrence

This commit is contained in:
amosblomqvist
2026-10-28 23:31:37 +02:00
parent de9caf6bc4
commit 6ff4924780
9 changed files with 343 additions and 56 deletions
+11 -10
View File
@@ -72,7 +72,7 @@ import { CoverageRing } from "@/components/extraction-coverage";
import { Button } from "@/components/ui/button";
import {
activeProblemOf,
danglingQuestionOf,
pendingQuestionOf,
dismissedAnswer,
endsInFailedTurn,
findPendingToolCall,
@@ -416,6 +416,7 @@ export function Chat({
void dismissQuestion(
p.toolCallId,
reading ? { ...answer, readingThinking: reading } : answer,
p.key,
);
if (busyRef.current) abortInFlightTurn();
return;
@@ -447,7 +448,7 @@ export function Chat({
// mount-only by design (turnInFlight read at initial value)
}, []);
const pending = findPendingToolCall(messages, danglingQuestionOf(nativeMessages)?.toolCallId ?? null);
const pending = findPendingToolCall(messages, pendingQuestionOf(nativeMessages));
// The abort handler reads the pending question from a ref (the window
// listener is mount-scoped; the value it needs is render-scoped).
const pendingRef = useRef(pending);
@@ -536,7 +537,7 @@ export function Chat({
readingThinkingRef.current = "";
setReadingThinking("");
}, []);
const pendingQuestionId = pending?.toolCallId ?? null;
const pendingQuestionId = pending?.key ?? null;
useEffect(() => {
// Different calls never share a draft; a failed submission of THIS
// call restores the reading channel alongside the form's snapshot.
@@ -1678,8 +1679,8 @@ export function Chat({
fold) and NEVER overlaps the composer. */}
<DockOverlay
pending={pending}
initialQuestionDraft={pending ? questionDraft(pending.toolCallId)?.form : undefined}
onSaveQuestionDraft={(form) => { if (pending) saveQuestionDraft(pending.toolCallId, { form }); }}
initialQuestionDraft={pending ? questionDraft(pending.key)?.form : undefined}
onSaveQuestionDraft={(form) => { if (pending) saveQuestionDraft(pending.key, { form }); }}
practice={activeProblem}
compactionRunning={compacting}
onSubmitThinking={submitThinking}
@@ -1749,11 +1750,11 @@ export function Chat({
// ride the same callback (QuestionAnswerData.dismissed). The
// reading-thinking draft rides along (owner 2026-10-03) — the
// check answer is its only carrier.
saveQuestionDraft(pending.toolCallId, { readingThinking: readingThinkingRef.current });
saveQuestionDraft(pending.key, { readingThinking: readingThinkingRef.current });
const reading = readingThinkingRef.current.trim() || undefined;
// The pending-id effect clears this only when the question
// actually leaves. An offline preflight keeps the draft visible.
submitAnswer(pending.tool, pending.toolCallId, reading ? { ...output, readingThinking: reading } : output);
submitAnswer(pending.tool, pending.toolCallId, reading ? { ...output, readingThinking: reading } : output, pending.key);
}}
/>
</Conversation>
@@ -1934,7 +1935,7 @@ function DockOverlay({
setupCta,
queuedSteers,
}: {
pending: ReturnType<typeof findPendingToolCall>;
pending: ReturnType<typeof pendingQuestionOf>;
initialQuestionDraft?: QuestionFormDraft;
onSaveQuestionDraft: (draft: QuestionFormDraft) => void;
/** Compaction running for this chat (round 14) — the docks' submit
@@ -2001,7 +2002,7 @@ function DockOverlay({
const [revealed, setRevealed] = useState(false);
const revealPending = requiresReveal && !revealed;
const pendingId = pending?.toolCallId ?? null;
const pendingId = pending?.key ?? null;
const initialPendingRef = useRef(pendingId);
// Teach-question ARRIVAL state, applied during render — BEFORE the
@@ -2064,7 +2065,7 @@ function DockOverlay({
const shellRef = useRef<HTMLDivElement>(null);
const contentRef = useRef<HTMLDivElement>(null);
const mode = pending
? `question:${pending.toolCallId}`
? `question:${pending.key}`
: practice
? `practice:${practice.toolCallId}`
: "chat";