import { updateCase, reconsiderCompletedEpisode } from "@/lib/graph/orchestrator.js"; import { applyValidatedProposal } from "@/lib/graph/apply-proposal.js"; import { prepareCompletedEpisode } from "@/lib/graph/episode-preparation.js"; import { updateCaseEpisodeRequestSchema } from "@/lib/graph/schema.js"; function mapFailureStatus(result) { switch (result?.stage) { case "request_validation": case "graph_validation": return 400; case "provider": return 502; case "proposal_validation": case "proposal_compatibility": case "application": return 422; case "result_validation": return 500; default: return 500; } } function buildFailureResponse(result) { return { success: false, stage: result?.stage ?? "internal", error: result?.error ?? "Update case failed", validationErrors: result?.validationErrors, graphValidationErrors: result?.graphValidationErrors, proposalErrors: result?.proposalErrors, providerErrors: result?.providerErrors, errors: result?.errors, diagnostics: result?.diagnostics, }; } export async function POST(request) { try { const body = await request.json(); const isEpisodeMode = body?.episodeMode === true; if (isEpisodeMode) { const parsed = updateCaseEpisodeRequestSchema.safeParse(body); if (!parsed.success) { return Response.json( { success: false, stage: "request_validation", error: "Invalid episode request", validationErrors: parsed.error.issues, }, { status: 400 }, ); } return await handleEpisodeMode(body.situationGraph, body); } const result = await updateCase(body, { applyProposal: true }); if (result.success) { return Response.json(result, { status: 200 }); } return Response.json(buildFailureResponse(result), { status: mapFailureStatus(result), }); } catch (error) { if (error instanceof SyntaxError) { return Response.json( { success: false, stage: "request_validation", error: "Invalid JSON request body", }, { status: 400 }, ); } return Response.json( { success: false, stage: "internal", error: "Internal server error", }, { status: 500 }, ); } } /** Server-side completed-episode reconsideration flow. */ async function handleEpisodeMode(situationGraph, body) { const prepared = prepareCompletedEpisode({ situationGraph, targetNodeId: body.targetNodeId, contributions: body.contributions ?? [], findings: body.findings, }); if (!prepared?.turns?.length && !prepared?.eligibleCanonicalFindings?.length) { return Response.json( { success: false, stage: "preparation", error: "no_episodic_content" }, { status: 400 }, ); } const reasoning = await reconsiderCompletedEpisode(prepared); if (!reasoning.success) { return Response.json( buildFailureResponse(reasoning), { status: mapFailureStatus(reasoning) }, ); } const application = await applyValidatedProposal({ situationGraph, proposal: reasoning.proposal, evidenceContext: { isCompletedEpisode: true, episodeEvidence: prepared, }, }); if (!application.success) { return Response.json( buildFailureResponse(application), { status: mapFailureStatus(application) }, ); } return Response.json({ success: true, updatedSituationGraph: application.updatedSituationGraph, proposal: reasoning.proposal, }, { status: 200 }); }