// Shared JSON extractor for HuggingFace chatCompletion responses. // Handles common Gemma malformations: trailing commas, unterminated strings, // unbalanced braces/brackets near the tail of the response. export function extractJson(raw: string): Record { const trimmed = raw.trim(); const candidates = [trimmed]; const match = trimmed.match(/\{[\s\S]*\}/); if (match) candidates.push(match[0]); for (const candidate of candidates) { try { return JSON.parse(candidate); } catch { // try repaired version } try { return JSON.parse(repairJson(candidate)); } catch { // continue } } throw new Error("could not parse JSON response"); } function repairJson(input: string): string { let s = input.trim(); s = s.replace(/,\s*([}\]])/g, "$1"); let inString = false; let escape = false; const stack: string[] = []; for (let i = 0; i < s.length; i++) { const ch = s[i]; if (escape) { escape = false; continue; } if (ch === "\\" && inString) { escape = true; continue; } if (ch === '"') { inString = !inString; continue; } if (inString) continue; if (ch === "{" || ch === "[") stack.push(ch); else if (ch === "}" && stack[stack.length - 1] === "{") stack.pop(); else if (ch === "]" && stack[stack.length - 1] === "[") stack.pop(); } if (inString) s += '"'; s = s.replace(/,\s*$/, ""); while (stack.length) { const open = stack.pop(); s += open === "{" ? "}" : "]"; } return s; }