/** * Situation Graph Case Orchestrator — manages the lifecycle of a case. * startCase builds initial graph from analysis; updateCase applies answers. */ import { analyseScenario } from "../analysis.js"; import { makeGraph, startCaseRequestSchema, situationGraphSchema, } from "./schema.js"; import { buildInitialGraph, describeGraph } from "./builder.js"; import { selectActiveUnknownCandidate, validateGraphReferences, } from "./utils.js"; function toValidationErrors(error) { return ( error?.errors?.map((issue) => ({ path: issue.path, message: issue.message, code: issue.code, })) ?? [{ message: "Validation failed" }] ); } function buildDiagnostics({ analysis, graph, graphReferenceValidation }) { return { promptVersion: analysis?.promptVersion ?? null, modelName: analysis?.modelName ?? null, responseDurationMs: analysis?.responseDurationMs ?? null, validationStatus: analysis?.validationStatus ?? "invalid", nodeCount: graph?.nodes?.length ?? 0, edgeCount: graph?.edges?.length ?? 0, graphReferenceValidation, compatibilityApplied: analysis?.compatibilityApplied ?? false, compatibilityChanges: analysis?.compatibilityChanges ?? [], compatibilityWarnings: analysis?.compatibilityWarnings ?? [], }; } export async function startCase(body) { const parsedRequest = startCaseRequestSchema.safeParse(body); if (!parsedRequest.success) { return { success: false, error: "Invalid start-case request", validationErrors: toValidationErrors(parsedRequest.error), statusCode: 400, }; } const { scenario, promptVersion } = parsedRequest.data; const analysis = await analyseScenario(scenario, { promptVersion }); if (!analysis.success) { return { success: false, error: analysis.error ?? "Scenario analysis failed", diagnostics: buildDiagnostics({ analysis, graph: null, graphReferenceValidation: null, }), analysisErrors: analysis.errors ?? undefined, rawResponse: analysis.rawResponse ?? undefined, statusCode: Number(analysis.statusCode) || 502, }; } const initialGraph = buildInitialGraph({ reconstruction: analysis.reconstruction, evidence: analysis.evidence, }); const currentSummary = describeGraph(initialGraph); const activeUnknownNodeId = selectActiveUnknownCandidate( { ...initialGraph, resolvedNodeIds: [], }, [], )?.nodeId ?? null; const situationGraph = makeGraph({ centralStatement: scenario, nodes: initialGraph.nodes, edges: initialGraph.edges, activeUnknownNodeId, resolvedNodeIds: [], currentSummary, }); situationGraphSchema.parse(situationGraph); const graphReferenceValidation = validateGraphReferences(situationGraph); if (!graphReferenceValidation.valid) { return { success: false, error: "Situation graph reference validation failed", diagnostics: buildDiagnostics({ analysis, graph: situationGraph, graphReferenceValidation, }), validationErrors: graphReferenceValidation.errors, statusCode: 500, }; } return { success: true, situationGraph, selectedQuestion: analysis.nextQuestion ?? null, diagnostics: buildDiagnostics({ analysis, graph: situationGraph, graphReferenceValidation, }), }; } export async function updateCase() { throw new Error("updateCase is not implemented yet"); }