diff --git a/.replit b/.replit index ca8fa0e..7b00032 100644 --- a/.replit +++ b/.replit @@ -26,10 +26,6 @@ externalPort = 3000 localPort = 43245 externalPort = 3001 -[[ports]] -localPort = 46341 -externalPort = 3003 - [env] PORT = "5000" diff --git a/after-login.png b/after-login.png new file mode 100644 index 0000000..0dc38eb Binary files /dev/null and b/after-login.png differ diff --git a/attached_assets/image_1759579547147.png b/attached_assets/image_1759579547147.png new file mode 100644 index 0000000..c316fa5 Binary files /dev/null and b/attached_assets/image_1759579547147.png differ diff --git a/attached_assets/image_1759581354334.png b/attached_assets/image_1759581354334.png new file mode 100644 index 0000000..91a8675 Binary files /dev/null and b/attached_assets/image_1759581354334.png differ diff --git a/attached_assets/image_1759581858245.png b/attached_assets/image_1759581858245.png new file mode 100644 index 0000000..e2b3f4f Binary files /dev/null and b/attached_assets/image_1759581858245.png differ diff --git a/server/services/openrouter.ts b/server/services/openrouter.ts index 88bedab..4d22b33 100644 --- a/server/services/openrouter.ts +++ b/server/services/openrouter.ts @@ -50,10 +50,18 @@ export class OpenRouterService { }); if (!response.ok) { + const errorText = await response.text(); + console.error('OpenRouter API Error Response:', errorText); throw new Error(`OpenRouter API error: ${response.status} ${response.statusText}`); } const data = await response.json(); + + if (!data.choices || !data.choices[0]) { + console.error('Invalid OpenRouter response - no choices:', { hasChoices: !!data.choices, model: config.model }); + throw new Error('Réponse invalide de l\'API OpenRouter. Vérifiez votre clé API et votre modèle.'); + } + const content = data.choices[0]?.message?.content || ""; return this.parseGeneratedText(content); @@ -90,9 +98,23 @@ VERSION 3 - ÉMOTIONNELLE: private parseGeneratedText(content: string): GeneratedText[] { const variants: GeneratedText[] = []; - const version1Match = content.match(/VERSION 1 - DYNAMIQUE:\s*\n([\s\S]*?)(?=VERSION 2|$)/i); - const version2Match = content.match(/VERSION 2 - INFORMATIVE:\s*\n([\s\S]*?)(?=VERSION 3|$)/i); - const version3Match = content.match(/VERSION 3 - ÉMOTIONNELLE:\s*\n([\s\S]*?)$/i); + // Normaliser les retours à la ligne (CRLF -> LF) + const normalizedContent = content.replace(/\r\n/g, '\n'); + + console.log('🔍 AI Response to parse (first 800 chars):\n', normalizedContent.substring(0, 800)); + console.log('🔍 AI Response length:', normalizedContent.length); + + // Regex ultra-flexibles acceptant: + // - markdown (** optionnel) + // - tirets variés (-, –, —) + // - espaces variables + // - deux-points optionnel + // - séparateurs (---, ***, etc.) + const version1Match = normalizedContent.match(/\*{0,2}\s*VERSION\s+1\s*[-–—]\s*DYNAMIQUE\s*\*{0,2}:?\s*[\r\n]+([\s\S]*?)(?=\s*[-*]{3,}\s*[\r\n]+|\*{0,2}\s*VERSION\s+2|$)/i); + const version2Match = normalizedContent.match(/\*{0,2}\s*VERSION\s+2\s*[-–—]\s*INFORMATIVE?\s*\*{0,2}:?\s*[\r\n]+([\s\S]*?)(?=\s*[-*]{3,}\s*[\r\n]+|\*{0,2}\s*VERSION\s+3|$)/i); + const version3Match = normalizedContent.match(/\*{0,2}\s*VERSION\s+3\s*[-–—]\s*[ÉE]MOTIONNELLE?\s*\*{0,2}:?\s*[\r\n]+([\s\S]*?)$/i); + + console.log('🔍 Matches found:', { v1: !!version1Match, v2: !!version2Match, v3: !!version3Match }); if (version1Match) { const text = version1Match[1].trim();