From f8cef758ad9a34d7bf5fe72d34481647b8ed5198 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Nov 2025 10:40:43 +0000 Subject: [PATCH] =?UTF-8?q?Fix:=20Am=C3=A9lioration=20des=20logs=20et=20ge?= =?UTF-8?q?stion=20d'erreurs=20pour=20l'assistant=20IA=20OpenRouter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problème : - Erreur 502 (Bad Gateway) sur /api/openrouter/chat - Message d'erreur générique "Provider returned error" peu informatif - Difficile de diagnostiquer la cause réelle du problème Solution backend (routes/openrouter.routes.js) : 1. Ajout de logs détaillés à chaque étape : - Début de requête avec modèle et nombre de messages - Validation de la clé API - Requête envoyée à OpenRouter - Réponse reçue avec status HTTP - Contenu de la réponse ou erreur détaillée 2. Amélioration de la gestion des erreurs : - Extraction du message d'erreur d'OpenRouter - Logs structurés avec contexte complet - Messages d'erreur plus descriptifs Solution frontend (src/services/OpenRouterService.ts) : 1. Ajout de logs console à chaque étape 2. Messages d'erreur contextuels selon le code HTTP : - 400 : Requête invalide (message d'erreur API) - 401 : Clé API invalide - 402 : Crédits épuisés - 429 : Trop de requêtes - 502/503 : Service temporairement indisponible 3. Validation de la réponse : - Vérification que le contenu existe - Message d'erreur si réponse vide Résultat : - Logs détaillés backend + frontend pour diagnostic - Messages d'erreur clairs et actionnables pour l'utilisateur - Meilleure traçabilité des problèmes OpenRouter --- routes/openrouter.routes.js | 46 +++++++++++++++++++++++++------ src/services/OpenRouterService.ts | 37 ++++++++++++++++++++++--- 2 files changed, 70 insertions(+), 13 deletions(-) diff --git a/routes/openrouter.routes.js b/routes/openrouter.routes.js index 6d3de69..ec05d24 100644 --- a/routes/openrouter.routes.js +++ b/routes/openrouter.routes.js @@ -143,7 +143,10 @@ router.post('/chat', authenticateToken, async (req, res) => { try { const { model, messages } = req.body; + logger.info(`[OPENROUTER CHAT] Début requête - model: "${model}", messages: ${messages?.length || 0}`); + if (!model || !messages || !Array.isArray(messages)) { + logger.warn('[OPENROUTER CHAT] Requête invalide - modèle ou messages manquants'); return res.status(400).json({ error: 'Modèle et messages requis' }); } @@ -151,11 +154,21 @@ router.post('/chat', authenticateToken, async (req, res) => { const setting = await getOne('SELECT value FROM settings WHERE key = $1', ['openrouter_api_key']); if (!setting || !setting.value) { - return res.status(400).json({ error: 'Clé API OpenRouter non configurée' }); + logger.warn('[OPENROUTER CHAT] Clé API non configurée'); + return res.status(400).json({ error: 'Clé API OpenRouter non configurée. Allez dans Paramètres pour la configurer.' }); } + logger.info(`[OPENROUTER CHAT] Clé API trouvée, appel à OpenRouter...`); + // Appeler l'API OpenRouter const fetch = (await import('node-fetch')).default; + const requestBody = { + model: model, + messages: messages + }; + + logger.info(`[OPENROUTER CHAT] Requête OpenRouter: ${JSON.stringify({ model, messageCount: messages.length })}`); + const response = await fetch('https://openrouter.ai/api/v1/chat/completions', { method: 'POST', headers: { @@ -164,25 +177,40 @@ router.post('/chat', authenticateToken, async (req, res) => { 'X-Title': 'NoteFlow', 'Content-Type': 'application/json' }, - body: JSON.stringify({ - model: model, - messages: messages - }) + body: JSON.stringify(requestBody) }); + logger.info(`[OPENROUTER CHAT] Réponse reçue - status: ${response.status} ${response.statusText}`); + if (!response.ok) { const errorData = await response.json().catch(() => ({})); - logger.error(`Erreur API OpenRouter chat: ${response.status}`, errorData); + const errorMessage = errorData.error?.message || errorData.error || `Erreur ${response.status}: ${response.statusText}`; + + logger.error(`[OPENROUTER CHAT] Erreur API OpenRouter:`, { + status: response.status, + statusText: response.statusText, + error: errorData + }); + return res.status(response.status).json({ - error: errorData.error?.message || 'Erreur lors de la communication avec l\'IA' + error: errorMessage }); } const data = await response.json(); + logger.info(`[OPENROUTER CHAT] Succès - réponse générée (${data.choices?.[0]?.message?.content?.length || 0} caractères)`); + res.json(data); } catch (error) { - logger.error('Erreur lors du chat OpenRouter:', error); - res.status(500).json({ error: 'Erreur serveur' }); + logger.error('[OPENROUTER CHAT] Erreur exception:', { + message: error.message, + stack: error.stack, + name: error.name + }); + + res.status(500).json({ + error: `Erreur serveur: ${error.message || 'Erreur inconnue'}` + }); } }); diff --git a/src/services/OpenRouterService.ts b/src/services/OpenRouterService.ts index a402429..7250ddb 100644 --- a/src/services/OpenRouterService.ts +++ b/src/services/OpenRouterService.ts @@ -60,6 +60,8 @@ class OpenRouterService { */ async sendMessage(model: string, messages: Array<{ role: string; content: string }>): Promise { try { + console.log(`[OpenRouter] Envoi requête - model: ${model}, messages: ${messages.length}`); + const response = await fetch('/api/openrouter/chat', { method: 'POST', headers: { @@ -69,15 +71,42 @@ class OpenRouterService { body: JSON.stringify({ model, messages }) }); + console.log(`[OpenRouter] Réponse reçue - status: ${response.status}`); + if (!response.ok) { - const error = await response.json().catch(() => ({ error: 'Erreur inconnue' })); - throw new Error(error.error || 'Erreur lors de la communication avec l\'IA'); + const errorData = await response.json().catch(() => ({ error: 'Erreur inconnue' })); + const errorMessage = errorData.error || `Erreur HTTP ${response.status}`; + + console.error('[OpenRouter] Erreur:', errorMessage); + + // Messages d'erreur plus clairs selon le code HTTP + if (response.status === 400) { + throw new Error(errorMessage); + } else if (response.status === 401) { + throw new Error('Clé API invalide. Vérifiez la configuration dans Paramètres.'); + } else if (response.status === 402) { + throw new Error('Crédits OpenRouter épuisés. Rechargez votre compte.'); + } else if (response.status === 429) { + throw new Error('Trop de requêtes. Attendez quelques instants.'); + } else if (response.status === 502 || response.status === 503) { + throw new Error('Service OpenRouter temporairement indisponible. Réessayez dans quelques instants.'); + } else { + throw new Error(errorMessage); + } } const data = await response.json(); - return data.choices?.[0]?.message?.content || 'Pas de réponse'; + const content = data.choices?.[0]?.message?.content; + + if (!content) { + console.error('[OpenRouter] Réponse vide:', data); + throw new Error('Aucune réponse générée par le modèle'); + } + + console.log(`[OpenRouter] Succès - ${content.length} caractères`); + return content; } catch (error: any) { - console.error('Erreur lors de l\'envoi du message:', error); + console.error('[OpenRouter] Erreur exception:', error); throw error; } }