import { PIPELINE_STEPS } from './primitives';
const STEP_LABELS = {
planning: 'Planning the research',
searching: 'Searching sources',
summarizing: 'Summarizing findings',
fact_checking: 'Cross-checking claims',
writing: 'Writing the report',
};
/**
* The five-step checklist, driven live by the SSE stream.
*
* Completed steps carry a check and their result detail, the active step carries an
* animated indicator, and upcoming steps sit behind ghosted glass rather than being
* greyed-out text — they are pending, not disabled.
*/
export default function ProgressChecklist({ completed, activeStep, finished }) {
return (
{PIPELINE_STEPS.map((step) => {
const done = completed[step.id];
const isActive = !done && step.id === activeStep && !finished;
const state = done ? 'is-done' : isActive ? 'is-active' : 'is-upcoming';
return (
-
{done ? '✓' : isActive ? : ''}
{STEP_LABELS[step.id]}
{done && {done.elapsed_sec}s}
{isActive && working…}
{done &&
}
);
})}
);
}
function StepDetail({ stepId, payload }) {
if (!payload) return null;
if (stepId === 'planning') {
const subQueries = payload.sub_queries || [];
if (!subQueries.length) return null;
return (
<>
Broke the question into {subQueries.length} sub-question{subQueries.length === 1 ? '' : 's'}:
{subQueries.map((sub) => (
- {sub}
))}
>
);
}
if (stepId === 'searching') {
return (
Retrieved {payload.source_count} unique source{payload.source_count === 1 ? '' : 's'}.
);
}
if (stepId === 'summarizing') {
return (
Extracted {payload.claim_count} claim{payload.claim_count === 1 ? '' : 's'} across{' '}
{payload.summarized_source_count} source{payload.summarized_source_count === 1 ? '' : 's'}.
);
}
if (stepId === 'fact_checking') {
const count = payload.contradiction_count ?? 0;
return (
{count === 0
? 'No contradictions found between sources.'
: `Flagged ${count} contradiction${count === 1 ? '' : 's'} between sources.`}
);
}
return null;
}