"use client";
import { useMemo } from "react";
// ── Confidence badge (shared) ────────────────────────
const confidenceColor = {
low: "text-red-600 bg-red-50 border-red-200",
medium: "text-yellow-700 bg-yellow-50 border-yellow-200",
high: "text-green-700 bg-green-50 border-green-200",
};
const ConfidenceBadge = ({ level }) => (
{level}
);
// ── Evidence type labels (shared) ───────────────────
const evidenceTypeLabels = {
direct_observation: "Direct Observation",
reported_statement: "Reported Statement",
interpretation: "Interpretation",
assumption: "Assumption",
inferred_relationship: "Inferred Relationship",
};
const importanceColors = {
incidental: "text-gray-500 bg-gray-50 border-gray-200",
supporting: "text-blue-700 bg-blue-50 border-blue-200",
important: "text-orange-700 bg-orange-50 border-orange-200",
critical: "text-red-800 bg-red-50 border-red-300 font-semibold",
};
const importanceLabels = {
incidental: "Incidental",
supporting: "Supporting",
important: "Important",
critical: "Critical",
};
// ── Input classification display ────────────────────
function ClassificationDisplay({ classification }) {
if (!classification) return null;
const p = classification.primaryType || classification.primary_type;
const sec = classification.secondaryTypes || classification.secondary_types || [];
const modes = classification.reasoningModes || classification.reasoning_modes || [];
// Normalize camelCase to snake_case for display if needed
const primaryLabel = String(p).replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
const secLabels = sec.map((s) => s.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()));
const modeLabels = modes.map((m) => m.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()));
return (
Input Classification
- Primary type
- {primaryLabel}
{secLabels.length > 0 && (
<>
- Secondary types
- {secLabels.join(" · ")}
>
)}
{modeLabels.length > 0 && (
<>
- Reasoning modes
- {modeLabels.join(" · ")}
>
)}
- Classification reason
- {classification.classificationReason || classification.classification_reason}
- Confidence
);
}
// ── Reconstruction summary ──────────────────────────
function SummaryDisplay({ reconstruction }) {
if (!reconstruction?.summary) return null;
const summary = reconstruction.summary || reconstruction.Summary;
return (
Reconstruction Summary
{summary}
);
}
// ── Generic item list (used for multiple sections) ──
function ItemList({ title, items, renderExtra }) {
const count = items?.length;
if (!count) return null; // hide empty sections entirely
const itemsArr = Array.isArray(items) ? items : [items];
return (
);
}
// ── Plausible interpretations ───────────────────────
function InterpretationsDisplay({ interpretations }) {
if (!interpretations?.length) return null;
const arr = Array.isArray(interpretations) ? interpretations : [interpretations];
return (
Plausible Interpretations ({arr.length})
{arr.map((interp, idx) => (
-
{interp.description}
{interp.confidence && }
{interp.supportingEvidenceIds?.length > 0 && (
Supporting evidence: {interp.supportingEvidenceIds.join(", ")}
)}
{interp.assumptionsRequired?.length > 0 && (
Requires assumptions: {interp.assumptionsRequired.join("; ")}
)}
))}
);
}
// ── Next question (prominent) ───────────────────────
function NextQuestionDisplay({ question }) {
if (!question?.question) return null;
const q = question.question || question.Question;
const targets = question.targets || question.Targets || [];
const reason = question.reason || question.Reason || "";
const value = question.expectedInformationValue || question.expected_information_value || "medium";
const valueLabel = { low: "Low", medium: "Medium", high: "High" }[value] || "Medium";
const valueColor = { low: "bg-yellow-100 text-yellow-800", medium: "bg-blue-100 text-blue-800", high: "bg-green-100 text-green-800" }[value] || "";
return (
Next Question
{valueLabel} value
{q}
{targets.length > 0 && (
Targets: {targets.join(", ")}
)}
{reason &&
Because: {reason}
}
);
}
// ── Evidence list ───────────────────────────────────
function EvidenceDisplay({ evidence }) {
if (!evidence?.length) return null;
const arr = Array.isArray(evidence) ? evidence : [evidence];
const evidenceLabels = {
direct_observation: "👁 Direct Observation",
reported_statement: "🗣 Reported Statement",
interpretation: "💡 Interpretation",
assumption: "❓ Assumption",
inferred_relationship: "🔗 Inferred Relationship",
};
return (
Supporting Evidence ({arr.length})
);
}
// ── Main component ──────────────────────────────────
export default function ReconstructionView({ reconstruction, partial }) {
// Handle both v0.2 direct object and wrapped result formats
const data = reconstruction;
if (partial) {
return (
⚠ Partial result — some fields failed validation. Showing what was accepted.
);
}
return (
{/* Classification first */}
{data.inputClassification && (
)}
{/* Summary */}
{data.reconstruction?.summary && (
)}
{/* Key differences */}
{data.reconstruction?.differences && (
)}
{/* Unexplained transitions */}
{data.reconstruction?.unexplainedTransitions && data.reconstruction.unexplainedTransitions.length > 0 && (
(
i.entity && Entity: {i.entity}
)} />
)}
{/* Contradictions */}
{data.reconstruction?.contradictions && data.reconstruction.contradictions.length > 0 && (
)}
{/* Important unknowns */}
{data.reconstruction?.importantUnknowns && data.reconstruction.importantUnknowns.length > 0 && (
)}
{/* Plausible interpretations */}
{data.reconstruction?.plausibleInterpretations && data.reconstruction.plausibleInterpretations.length > 0 && (
)}
{/* Secondary reconstruction categories (actors, systems, etc.) */}
{data.reconstruction?.actors && data.reconstruction.actors.length > 0 && (
)}
{data.reconstruction?.systemsOrObjects && data.reconstruction.systemsOrObjects.length > 0 && (
)}
{data.reconstruction?.expectedStates && data.reconstruction.expectedStates.length > 0 && (
)}
{data.reconstruction?.observedStates && data.reconstruction.observedStates.length > 0 && (
)}
{data.reconstruction?.knownTransitions && data.reconstruction.knownTransitions.length > 0 && (
(
{i.entity && Entity: {i.entity} · }
From "{i.previousState}" → To "{i.currentState}" ({i.explanationStatus})
)} />
)}
{/* Next question — prominent */}
{/* Evidence */}
{data.evidence && (
)}
);
}