From d5977c884557555f4cf37bd33aed816d6924c476 Mon Sep 17 00:00:00 2001 From: MythEclipse Date: Thu, 14 May 2026 04:00:31 +0700 Subject: [PATCH] fix: handle streaming JSON response from AI LLM API - Fix fetchJson to extract JSON from streaming response text - API returns text/event-stream with complete JSON object embedded - Extract JSON by finding first { and last } in response - Prevents "Unexpected non-whitespace character after JSON" parse errors - Streaming response now properly parsed and analyzed This resolves: - AI analysis stuck on "[Streaming in progress...]" - JSON parse failures on streaming responses - AI analysis now completes successfully Co-Authored-By: Claude Opus 4.7 --- src/moderation/aiAnalyzer.ts | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/moderation/aiAnalyzer.ts b/src/moderation/aiAnalyzer.ts index 245297f..06d290a 100644 --- a/src/moderation/aiAnalyzer.ts +++ b/src/moderation/aiAnalyzer.ts @@ -36,14 +36,27 @@ async function fetchJson(url: string, init: RequestInit): Promise { try { const response = await fetch(url, { ...init, signal: controller.signal }); - const body = await response.json().catch(() => ({})); + const text = await response.text(); + if (!response.ok) { - const message = typeof body === "object" && body && "error" in body - ? JSON.stringify(body) - : response.statusText; + const message = text.includes("{") + ? JSON.stringify(JSON.parse(text.substring(text.indexOf("{")))) + : text; throw new Error(`AI request failed (${response.status}): ${message}`); } - return body; + + // Handle streaming response: extract JSON from response text + const jsonStart = text.indexOf("{"); + const jsonEnd = text.lastIndexOf("}"); + if (jsonStart >= 0 && jsonEnd > jsonStart) { + try { + return JSON.parse(text.substring(jsonStart, jsonEnd + 1)); + } catch { + // Fall through to parse full text + } + } + + return JSON.parse(text); } finally { clearTimeout(timeout); }