/** * Typed fetch wrappers for the Next-Gen evaluation API (/api/nextgen). * Mirrors the style of services/rca.ts. */ import type { ArchitectureDocs, BehavioralAssessment, CatalogueEntry, CausalReplayResult, ComputeReport, CounterfactualScenario, DivergenceDemo, GauntletResult, NextgenStatus, SuiteWeights, TransformationStep, ValidityReport, } from '../types/nextgen'; async function handle(res: Response): Promise { if (!res.ok) { let detail = ''; try { const body = await res.json(); detail = typeof body?.detail === 'string' ? body.detail : JSON.stringify(body); } catch { detail = await res.text().catch(() => ''); } const err = new Error(detail || res.statusText) as Error & { status?: number }; err.status = res.status; throw err; } return res.json() as Promise; } const JSON_HEADERS = { 'Content-Type': 'application/json' }; const get = (url: string): Promise => fetch(url).then((r) => handle(r)); const post = (url: string, body?: unknown): Promise => fetch(url, { method: 'POST', headers: JSON_HEADERS, body: body === undefined ? undefined : JSON.stringify(body), }).then((r) => handle(r)); export const getStatus = () => get('/api/nextgen/status'); export const getCatalogue = () => get<{ transformations: CatalogueEntry[] }>('/api/nextgen/counterfactuals/catalogue'); export const generateCounterfactuals = (body: { recipe: TransformationStep[]; seed?: number; n_scenarios?: number; frames_per_sequence?: number; }) => post<{ scenarios: CounterfactualScenario[] }>('/api/nextgen/counterfactuals/generate', body); export const listCounterfactuals = () => get<{ scenarios: CounterfactualScenario[] }>('/api/nextgen/counterfactuals'); export const validateCounterfactual = (scenarioId: string) => post(`/api/nextgen/counterfactuals/${encodeURIComponent(scenarioId)}/validate`); export const getSuiteWeights = () => get('/api/nextgen/counterfactuals/suite-weights'); export const runReplay = (body: { scenario_id: string; engine?: string; seed?: number; corrected?: boolean; faults?: Record[]; }) => post('/api/nextgen/simulation/replay', body); export const runCausalReplay = (body: { scenario_id: string; engine?: string; seed?: number; faults?: Record[]; }) => post('/api/nextgen/causal/replay', body); export const getDivergenceDemo = () => get('/api/nextgen/metrics/divergence-demo'); export const runGauntlet = (body: { candidate_version?: string; baseline_version?: string; effects?: Record; budget_units?: number; batch_units?: number; seed?: number; }) => post('/api/nextgen/gauntlet/run', body); export const getGauntletResults = (runId: string) => get(`/api/nextgen/gauntlet/${encodeURIComponent(runId)}/results`); export const runComputeBenchmark = (body: { n_scenarios?: number; frames_per_sequence?: number }) => post('/api/nextgen/compute/benchmark', body); export const getComputeReport = () => get('/api/nextgen/compute/report'); export const getArchitectureDocs = () => get('/api/nextgen/architecture/docs');