From c473e54ae849e2bdc0508332b72cc550e4af1245 Mon Sep 17 00:00:00 2001 From: Hermann_Kitio Date: Sat, 25 Apr 2026 07:41:58 +0300 Subject: [PATCH] fix(deepseek): handle single-quote JSON from DeepSeek responses Co-Authored-By: Claude Opus 4.7 (1M context) --- src/lib/deepseek.ts | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/lib/deepseek.ts b/src/lib/deepseek.ts index 194872f..6183664 100644 --- a/src/lib/deepseek.ts +++ b/src/lib/deepseek.ts @@ -403,17 +403,37 @@ export function truncateToMaxWords( // ── Appels DeepSeek ────────────────────────────────────────────────────── /** - * Strip d'éventuels fences markdown autour d'une réponse JSON. + * Nettoie une réponse DeepSeek avant `JSON.parse`. * - * DeepSeek wrappe parfois sa sortie dans des blocs ```json ... ``` malgré - * `response_format: { type: "json_object" }`. On retire ces fences avant - * `JSON.parse` pour éviter `SyntaxError: Expected property name`. + * Deux dérives observées malgré `response_format: { type: "json_object" }` : + * 1. Wrap markdown ```json … ``` (rare mais arrive). + * 2. Guillemets simples au lieu de doubles (`'key': 'value'`) — voire + * des chevrons « ... ». Diagnostiqué Sprint 4b (correction EO). + * + * Stratégie défensive : + * - Strip systématique des fences markdown. + * - Tentative JSON.parse en l'état → si OK, on retourne tel quel. + * - Sinon : remplacement des single quotes JSON par des doubles, en + * préservant les apostrophes légitimes à l'intérieur des valeurs + * (heuristique : on bascule les `\'` échappés en `'` après le swap). */ function sanitizeJsonContent(raw: string): string { - return raw - .replace(/^\s*```(?:json)?\s*/i, "") - .replace(/\s*```\s*$/i, "") + let cleaned = raw + .replace(/```json\s*/gi, "") + .replace(/```\s*/g, "") .trim(); + + try { + JSON.parse(cleaned); + return cleaned; + } catch { + // Fallback : DeepSeek a renvoyé du « pseudo-JSON » avec single quotes. + // 1. Remplace toutes les `'` par `"` (suffisant dans la plupart des cas). + // 2. Restaure les apostrophes échappées : `\"` (résultat du swap sur un + // `\'` original) redevient `'`. + cleaned = cleaned.replace(/'/g, '"').replace(/\\"/g, "'"); + return cleaned; + } } async function callDeepSeek(