fix: tracer le moteur IA réellement invoqué
All checks were successful
Validation applicative / TypeScript, tests et build (push) Successful in 1m52s

This commit is contained in:
Manus Deployment
2026-09-09 08:27:43 +00:00
parent f7cfa73206
commit 7754affe96
7 changed files with 2659 additions and 16 deletions

View File

@@ -97,6 +97,29 @@ export type InvokeResult = {
};
};
export type LlmProvider = "mistral" | "manus" | "gemini";
export type LlmTransport = "mistral-api" | "manus-forge" | "gemini-api";
export type UserLlmSettings = {
aiProvider?: string | null;
mistralApiKey?: string | null;
manusForgeApiKey?: string | null;
manusForgeApiUrl?: string | null;
geminiApiKey?: string | null;
};
/** Métadonnées non sensibles décrivant l’appel LLM réellement résolu. */
export type ResolvedLlmTrace = {
provider: LlmProvider;
model: string;
transport: LlmTransport;
};
export type ResolvedLlmInvocation = {
response: InvokeResult;
trace: ResolvedLlmTrace;
};
export type JsonSchema = {
name: string;
schema: Record<string, unknown>;
@@ -283,7 +306,7 @@ const normalizeResponseFormat = ({
/**
* Résout l'URL API en tenant compte des paramètres utilisateur (DB) en priorité sur les variables d'environnement.
*/
function resolveApiUrlWithSettings(settings?: { aiProvider?: string | null; mistralApiKey?: string | null; manusForgeApiKey?: string | null; manusForgeApiUrl?: string | null; geminiApiKey?: string | null }): string {
function resolveApiUrlWithSettings(settings?: UserLlmSettings): string {
const provider = settings?.aiProvider || "mistral";
if (provider === "mistral") {
return "https://api.mistral.ai/v1/chat/completions";
@@ -297,7 +320,7 @@ function resolveApiUrlWithSettings(settings?: { aiProvider?: string | null; mist
return `${forgeUrl.replace(/\/$/, "")}/v1/chat/completions`;
}
function getApiKeyWithSettings(settings?: { aiProvider?: string | null; mistralApiKey?: string | null; manusForgeApiKey?: string | null; geminiApiKey?: string | null }): string {
function getApiKeyWithSettings(settings?: UserLlmSettings): string {
const provider = settings?.aiProvider || "mistral";
if (provider === "mistral") {
return settings?.mistralApiKey || ENV.mistralApiKey || "";
@@ -308,11 +331,20 @@ function getApiKeyWithSettings(settings?: { aiProvider?: string | null; mistralA
return settings?.manusForgeApiKey || ENV.forgeApiKey || "";
}
function getModelForProvider(provider: string): string {
if (provider === "mistral") return "mistral-large-latest";
if (provider === "gemini") return "gemini-2.0-flash";
// Manus Forge → Gemini 2.5 Flash via proxy
return "gemini-2.5-flash";
/**
* Résout le fournisseur, le modèle et la passerelle effectivement utilisés.
* Cette trace ne contient aucun secret ni URL personnalisée.
*/
export function resolveLlmTrace(settings?: UserLlmSettings): ResolvedLlmTrace {
const provider = settings?.aiProvider || "mistral";
if (provider === "manus") {
return { provider: "manus", model: "gemini-2.5-flash", transport: "manus-forge" };
}
if (provider === "gemini") {
return { provider: "gemini", model: "gemini-2.0-flash", transport: "gemini-api" };
}
return { provider: "mistral", model: "mistral-large-latest", transport: "mistral-api" };
}
/**
@@ -321,14 +353,15 @@ function getModelForProvider(provider: string): string {
*/
export async function invokeLLMWithUserSettings(
params: InvokeParams,
userSettings?: { aiProvider?: string | null; mistralApiKey?: string | null; manusForgeApiKey?: string | null; manusForgeApiUrl?: string | null; geminiApiKey?: string | null }
): Promise<InvokeResult> {
userSettings?: UserLlmSettings
): Promise<ResolvedLlmInvocation> {
const apiKey = getApiKeyWithSettings(userSettings);
if (!apiKey || apiKey.trim().length === 0) {
throw new Error("Aucune clé API configurée pour le moteur IA sélectionné");
}
const provider = userSettings?.aiProvider || "mistral";
const trace = resolveLlmTrace(userSettings);
const provider = trace.provider;
const {
messages,
@@ -341,7 +374,7 @@ export async function invokeLLMWithUserSettings(
response_format,
} = params;
const model = getModelForProvider(provider);
const model = trace.model;
const payload: Record<string, unknown> = {
model,
@@ -378,7 +411,10 @@ export async function invokeLLMWithUserSettings(
throw new Error(`LLM invoke failed: ${response.status} ${response.statusText} – ${errorText}`);
}
return (await response.json()) as InvokeResult;
return {
response: (await response.json()) as InvokeResult,
trace,
};
}
export async function invokeLLM(params: InvokeParams): Promise<InvokeResult> {