fix: tracer le moteur IA réellement invoqué
All checks were successful
Validation applicative / TypeScript, tests et build (push) Successful in 1m52s
All checks were successful
Validation applicative / TypeScript, tests et build (push) Successful in 1m52s
This commit is contained in:
@@ -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> {
|
||||
|
||||
Reference in New Issue
Block a user