fix: address console review findings
This commit is contained in:
@@ -1,16 +1,24 @@
|
||||
import { useMemo, useState } from "react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { ldaReportSetupCommands } from "./ldaReportDemoConfig.js";
|
||||
import { DemoTimelineControls } from "./DemoTimelineControls.js";
|
||||
import { DemoTimeline } from "./DemoTimeline.js";
|
||||
import type { DemoTimelineController } from "./useDemoTimeline.js";
|
||||
|
||||
const DEFAULT_REVIEW_COMMENT = "Create selected issues before the defense.";
|
||||
|
||||
export const LdaReportDemoPanel = ({ controller }: { readonly controller: DemoTimelineController }) => {
|
||||
const { state } = controller;
|
||||
const [selectedIds, setSelectedIds] = useState<ReadonlySet<string>>(new Set());
|
||||
const [comment, setComment] = useState("Create selected issues before the defense.");
|
||||
const [comment, setComment] = useState(DEFAULT_REVIEW_COMMENT);
|
||||
|
||||
const proposedIssues = controller.interruptPayload?.proposed_issues ?? [];
|
||||
const selectedIssueIds = useMemo(() => [...selectedIds], [selectedIds]);
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedIds(new Set());
|
||||
setComment(DEFAULT_REVIEW_COMMENT);
|
||||
}, [state.mode, state.phase, controller.interruptPayload]);
|
||||
|
||||
return (
|
||||
<section aria-label="lda report workflow demo" className="demo-panel">
|
||||
<div className="demo-panel__header">
|
||||
|
||||
@@ -51,6 +51,25 @@ export type LiveStepResult = {
|
||||
readonly events: ReadonlyArray<DemoEvent>;
|
||||
};
|
||||
|
||||
const baseDemoEvent = (
|
||||
context: LiveDemoContext,
|
||||
stage: DemoEventStage,
|
||||
runId: string | null,
|
||||
sequenceOffset = 0,
|
||||
): Pick<DemoEvent, "id" | "sequence" | "stage" | "resultingIds" | "recordedAt"> => {
|
||||
const sequence = context.nextSequence + sequenceOffset;
|
||||
return {
|
||||
id: `live-${sequence}-${stage}-${runId ?? "pending"}`,
|
||||
sequence,
|
||||
stage,
|
||||
resultingIds: {
|
||||
deploymentId: LDA_REPORT_DEPLOYMENT_ID,
|
||||
runId,
|
||||
},
|
||||
recordedAt: new Date().toISOString(),
|
||||
};
|
||||
};
|
||||
|
||||
const eventFromResult = (
|
||||
context: LiveDemoContext,
|
||||
stage: DemoEventStage,
|
||||
@@ -60,9 +79,7 @@ const eventFromResult = (
|
||||
result: RpcResponse,
|
||||
runId: string | null,
|
||||
): DemoEvent => ({
|
||||
id: `live-${context.nextSequence}-${stage}-${runId ?? "pending"}`,
|
||||
sequence: context.nextSequence,
|
||||
stage,
|
||||
...baseDemoEvent(context, stage, runId),
|
||||
operation,
|
||||
reason: result.ok ? reason : result.error.message,
|
||||
equivalentCli: result.ok ? result.equivalentCli : null,
|
||||
@@ -70,11 +87,6 @@ const eventFromResult = (
|
||||
rawResponse: result.exchange.response,
|
||||
interpreted: result.ok ? result.interpreted : null,
|
||||
durationMs: result.ok ? result.durationMs : 0,
|
||||
resultingIds: {
|
||||
deploymentId: LDA_REPORT_DEPLOYMENT_ID,
|
||||
runId,
|
||||
},
|
||||
recordedAt: new Date().toISOString(),
|
||||
});
|
||||
|
||||
const syntheticEvent = (
|
||||
@@ -85,9 +97,7 @@ const syntheticEvent = (
|
||||
runId: string | null,
|
||||
sequenceOffset = 0,
|
||||
): DemoEvent => ({
|
||||
id: `live-${context.nextSequence + sequenceOffset}-${stage}-${runId ?? "pending"}`,
|
||||
sequence: context.nextSequence + sequenceOffset,
|
||||
stage,
|
||||
...baseDemoEvent(context, stage, runId, sequenceOffset),
|
||||
operation: null,
|
||||
reason,
|
||||
equivalentCli: null,
|
||||
@@ -95,8 +105,6 @@ const syntheticEvent = (
|
||||
rawResponse: null,
|
||||
interpreted,
|
||||
durationMs: 0,
|
||||
resultingIds: { deploymentId: LDA_REPORT_DEPLOYMENT_ID, runId },
|
||||
recordedAt: new Date().toISOString(),
|
||||
});
|
||||
|
||||
const operationForStage = (stage: LiveDemoStage): string | null => {
|
||||
@@ -118,9 +126,7 @@ export const failedLiveDemoEvent = (
|
||||
context: LiveDemoContext,
|
||||
reason: string,
|
||||
): DemoEvent => ({
|
||||
id: `live-${context.nextSequence}-failed-${context.runId ?? "pending"}`,
|
||||
sequence: context.nextSequence,
|
||||
stage: "failed",
|
||||
...baseDemoEvent(context, "failed", context.runId),
|
||||
operation: operationForStage(context.nextStage),
|
||||
reason,
|
||||
equivalentCli: null,
|
||||
@@ -128,11 +134,6 @@ export const failedLiveDemoEvent = (
|
||||
rawResponse: null,
|
||||
interpreted: null,
|
||||
durationMs: 0,
|
||||
resultingIds: {
|
||||
deploymentId: LDA_REPORT_DEPLOYMENT_ID,
|
||||
runId: context.runId,
|
||||
},
|
||||
recordedAt: new Date().toISOString(),
|
||||
});
|
||||
|
||||
export const executeLiveDemoStep = async (
|
||||
@@ -238,6 +239,19 @@ export const executeLiveDemoStep = async (
|
||||
};
|
||||
}
|
||||
const detail = decodeRunDetail(result.interpreted);
|
||||
if (detail.status !== "completed") {
|
||||
const failed = syntheticEvent(
|
||||
context,
|
||||
"failed",
|
||||
`Demo resume returned ${detail.status} instead of completed.`,
|
||||
result.interpreted,
|
||||
detail.runId,
|
||||
);
|
||||
return {
|
||||
events: [failed],
|
||||
context: { ...context, nextStage: "done", runId: detail.runId, nextSequence: context.nextSequence + 1 },
|
||||
};
|
||||
}
|
||||
const output = parseLdaReportOutput(detail.output);
|
||||
return {
|
||||
events: [eventFromResult(context, "run_resume", "workflow.runs.resume", "Resume the interrupted run.", params, result, context.runId)],
|
||||
|
||||
@@ -63,6 +63,7 @@ export const useDemoTimeline = (
|
||||
const recordEvidenceRef = useRef(recordEvidence);
|
||||
recordEvidenceRef.current = recordEvidence;
|
||||
const inFlightRef = useRef(false);
|
||||
const generationRef = useRef(0);
|
||||
const [inFlight, setInFlight] = useState(false);
|
||||
const approvalRef = useRef<DemoApproval | null>(null);
|
||||
const activeRecording = useRef(loadCanonicalDemoRecording());
|
||||
@@ -71,9 +72,25 @@ export const useDemoTimeline = (
|
||||
const [output, setOutput] = useState<LdaReportOutput | null>(null);
|
||||
const [trace, setTrace] = useState<TracePage | null>(null);
|
||||
|
||||
const resetRuntime = useCallback(() => {
|
||||
generationRef.current++;
|
||||
inFlightRef.current = false;
|
||||
setInFlight(false);
|
||||
liveContextRef.current = initialLiveDemoContext;
|
||||
approvalRef.current = null;
|
||||
setInterruptPayload(null);
|
||||
setOutput(null);
|
||||
setTrace(null);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
resetRuntime();
|
||||
}, [target, resetRuntime]);
|
||||
|
||||
const step = useCallback(async () => {
|
||||
if (inFlightRef.current) return;
|
||||
if (state.appliedCount >= state.events.length && state.mode === "replay") return;
|
||||
const generation = generationRef.current;
|
||||
inFlightRef.current = true;
|
||||
setInFlight(true);
|
||||
try {
|
||||
@@ -102,6 +119,7 @@ export const useDemoTimeline = (
|
||||
const approval = approvalRef.current;
|
||||
approvalRef.current = null;
|
||||
const result = await executeLiveDemoStep(target, liveContextRef.current, approval ?? undefined);
|
||||
if (generation !== generationRef.current) return;
|
||||
liveContextRef.current = result.context;
|
||||
for (const event of result.events) {
|
||||
dispatch({ type: "append_live_event", event });
|
||||
@@ -162,8 +180,10 @@ export const useDemoTimeline = (
|
||||
dispatch({ type: "fail", message });
|
||||
}
|
||||
} finally {
|
||||
inFlightRef.current = false;
|
||||
setInFlight(false);
|
||||
if (generation === generationRef.current) {
|
||||
inFlightRef.current = false;
|
||||
setInFlight(false);
|
||||
}
|
||||
}
|
||||
}, [state.mode, state.appliedCount, state.events, target]);
|
||||
|
||||
@@ -177,25 +197,19 @@ export const useDemoTimeline = (
|
||||
}, [state.phase, state.autoplay, state.appliedCount, step]);
|
||||
|
||||
const setMode = useCallback((mode: DemoMode) => {
|
||||
resetRuntime();
|
||||
dispatch({ type: "set_mode", mode });
|
||||
liveContextRef.current = initialLiveDemoContext;
|
||||
setInterruptPayload(null);
|
||||
setOutput(null);
|
||||
setTrace(null);
|
||||
}, []);
|
||||
}, [resetRuntime]);
|
||||
|
||||
const start = useCallback(() => {
|
||||
resetRuntime();
|
||||
if (state.mode === "replay") {
|
||||
const recording = activeRecording.current;
|
||||
dispatch({ type: "start", mode: "replay", events: recording.events });
|
||||
} else {
|
||||
liveContextRef.current = initialLiveDemoContext;
|
||||
dispatch({ type: "start", mode: "live", events: [] });
|
||||
}
|
||||
setInterruptPayload(null);
|
||||
setOutput(null);
|
||||
setTrace(null);
|
||||
}, [state.mode]);
|
||||
}, [resetRuntime, state.mode]);
|
||||
|
||||
const pause = useCallback(() => dispatch({ type: "pause" }), []);
|
||||
const play = useCallback(() => dispatch({ type: "play" }), []);
|
||||
@@ -229,12 +243,9 @@ export const useDemoTimeline = (
|
||||
}, []);
|
||||
|
||||
const restart = useCallback(() => {
|
||||
resetRuntime();
|
||||
dispatch({ type: "restart" });
|
||||
liveContextRef.current = initialLiveDemoContext;
|
||||
setInterruptPayload(null);
|
||||
setOutput(null);
|
||||
setTrace(null);
|
||||
}, []);
|
||||
}, [resetRuntime]);
|
||||
|
||||
return {
|
||||
state,
|
||||
|
||||
Reference in New Issue
Block a user