import { ENV } from "./env"; export type ResolvedAiTrace = { provider: string; resolvedModel: string; transport: string; origin: string; }; function configuration() { const url = ENV.aiReferentielUrl.trim().replace(/\/$/, ""); const token = ENV.aiReferentielToken.trim(); if (!url || !token) { throw new Error("Référentiel IA non configuré pour cette application."); } return { url, token }; } /** * Le Référentiel décide seul du moteur et écrase tout modèle éventuellement * présent dans le payload. La trace détaillée est persistée centralement. */ export async function invokeSelectedReference(payload: Record, fetcher: typeof fetch = fetch): Promise { const { url, token } = configuration(); const response = await fetcher(`${url}/api/integration/v1/invoke`, { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${token}`, }, body: JSON.stringify({ payload }), signal: AbortSignal.timeout(120_000), }); if (!response.ok) { throw new Error(`Référentiel IA : invocation refusée (HTTP ${response.status}).`); } const trace: ResolvedAiTrace = { provider: response.headers.get("x-santinova-ia-provider") || "unknown", resolvedModel: response.headers.get("x-santinova-ia-model") || "unknown", transport: response.headers.get("x-santinova-ia-transport") || "unknown", origin: response.headers.get("x-santinova-ia-origin") || "unknown", }; console.info(`[IA_TRACE] provider=${trace.provider} model=${trace.resolvedModel} transport=${trace.transport} origin=${trace.origin}`); const body = await response.json() as unknown; if (body && typeof body === "object" && "error" in body) { const message = typeof (body as { error?: { message?: unknown } }).error?.message === "string" ? (body as { error: { message: string } }).error.message : "erreur non détaillée"; throw new Error(`Référentiel IA : ${message}`); } return body as T; }