Merge pull request #962 from pikasTech/fix/issue955-stable-replay-timer
fix: keep compact trace replay timers stable
This commit is contained in:
@@ -52,10 +52,23 @@ test("conversation panel does not consume replay opportunity before timer fires"
|
||||
const effectStart = source.indexOf("const replayRequestedTraceRef = useRef<string | null>(null);");
|
||||
const timerStart = source.indexOf("const timer = window.setTimeout", effectStart);
|
||||
const markRequested = source.indexOf("replayRequestedTraceRef.current = traceId", effectStart);
|
||||
const replayCall = source.indexOf("onReplayTrace();", effectStart);
|
||||
const replayCall = source.indexOf("replayHandlerRef.current();", effectStart);
|
||||
|
||||
assert.ok(effectStart > 0, "replay guard ref exists");
|
||||
assert.ok(timerStart > effectStart, "auto replay uses delayed timer");
|
||||
assert.ok(markRequested > timerStart, "route changes that cancel the timer must not mark replay as already requested");
|
||||
assert.ok(replayCall > markRequested, "replay is marked requested only immediately before dispatching replay");
|
||||
});
|
||||
|
||||
test("conversation panel keeps replay timer stable across parent rerenders", async () => {
|
||||
const source = await Bun.file(new URL("./ConversationPanel.tsx", import.meta.url)).text();
|
||||
const handlerRef = source.indexOf("const replayHandlerRef = useRef(onReplayTrace);");
|
||||
const effectStart = source.indexOf("const timer = window.setTimeout", handlerRef);
|
||||
const effectEnd = source.indexOf("if (message.role === \"agent\")", effectStart);
|
||||
const effectSource = source.slice(effectStart, effectEnd);
|
||||
|
||||
assert.ok(handlerRef > 0, "onReplayTrace is kept behind a stable ref");
|
||||
assert.match(effectSource, /replayHandlerRef\.current\(\);/u);
|
||||
assert.match(effectSource, /\}, \[shouldReplayTrace, traceId\]\);/u);
|
||||
assert.doesNotMatch(effectSource, /\bonReplayTrace\b/u);
|
||||
});
|
||||
|
||||
@@ -131,16 +131,21 @@ const HISTORICAL_TRACE_REPLAY_DELAY_MS = 4500;
|
||||
function MessageCard({ message, firstScreenHistory, codeAgentTimeoutMs, onCancel, onRetry, onReplayTrace }: { message: ChatMessage; firstScreenHistory: boolean; codeAgentTimeoutMs: number; onCancel(): void; onRetry(): void; onReplayTrace(): void }): ReactElement {
|
||||
const traceKey = `hwlab.workbench.trace-open.${message.traceId ?? message.id}`;
|
||||
const replayRequestedTraceRef = useRef<string | null>(null);
|
||||
const replayHandlerRef = useRef(onReplayTrace);
|
||||
useEffect(() => {
|
||||
replayHandlerRef.current = onReplayTrace;
|
||||
}, [onReplayTrace]);
|
||||
const traceId = message.traceId ?? message.runnerTrace?.traceId ?? null;
|
||||
const shouldReplayTrace = shouldAutoReplayTrace(message);
|
||||
useEffect(() => {
|
||||
const traceId = message.traceId ?? message.runnerTrace?.traceId ?? null;
|
||||
if (traceId && replayRequestedTraceRef.current === traceId) return;
|
||||
if (!shouldAutoReplayTrace(message)) return;
|
||||
if (!shouldReplayTrace) return;
|
||||
const timer = window.setTimeout(() => {
|
||||
replayRequestedTraceRef.current = traceId;
|
||||
onReplayTrace();
|
||||
replayHandlerRef.current();
|
||||
}, HISTORICAL_TRACE_REPLAY_DELAY_MS);
|
||||
return () => window.clearTimeout(timer);
|
||||
}, [message, onReplayTrace]);
|
||||
}, [shouldReplayTrace, traceId]);
|
||||
if (message.role === "agent") {
|
||||
const hasFinalResponse = message.status !== "running" && message.text.trim().length > 0;
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user