/** * Reusable live-focused-deconstruction experiment helper. * * Makes one real focused-deconstruction call using the same production * semantic operation as /api/focused-investigation/deconstruct: * * buildFocusedDeconstructPrompt -> provider.generateReconstruction -> validateFocusedDeconstructSchema * * Inputs are the minimum fields required by buildFocusedDeconstructPrompt. * Relies on environment variables OLLAMA_BASE_URL and OLLAMA_MODEL being set. */ import { buildFocusedDeconstructPrompt, validateFocusedDeconstructSchema } from "@/lib/graph/focused-investigation.js"; import { getProvider } from "@/lib/llm/provider.js"; /** * Run one live focused-deconstruction experiment. * * @param {object} params * @param {string} params.targetNodeId - the target node ID under investigation * @param {string} params.targetLabel - label of the target node * @param {string} params.targetDescription - description of the target node * @param {string} params.centralStatement - the case's central statement * @param {string} params.question - the exact real production question * @param {string} params.answer - the exact real production answer * @param {object} [params.provider] - optional injected provider (for test isolation) * @returns {object} validated result + timing details */ export async function runLiveFocusedDeconstructExperiment(params) { const { targetNodeId, targetLabel, targetDescription, centralStatement, question, answer, provider } = params; // Production path: real prompt builder (never copies prompt logic) const prompt = buildFocusedDeconstructPrompt({ targetLabel, targetDescription, centralStatement, question, answer, }); // Provider: use injected (test) or real (production) const actualProvider = provider ?? getProvider(); const ollamaModel = process.env.OLLAMA_MODEL; if (!ollamaModel) throw new Error("OLLAMA_MODEL is not set in environment"); const startedAt = Date.now(); const raw = await actualProvider.generateReconstruction(prompt, ollamaModel); const elapsedMs = Date.now() - startedAt; // Production path: real schema validator (never copies schema logic) const validationErrors = validateFocusedDeconstructSchema(raw); if (validationErrors.length > 0) { throw new Error( "Focused deconstruction result did not match expected schema:\n" + validationErrors.map((e) => " - " + e).join("\n") ); } return { success: true, targetNodeId, observations: raw.observations, uncertainties: raw.uncertainties, assumptions: raw.assumptions, relationships: raw.relationships, possibleFollowUpQuestions: raw.possibleFollowUpQuestions, elapsedMs, }; } export { buildFocusedDeconstructPrompt, validateFocusedDeconstructSchema };