| export function safeJsonParse(text: string): any { |
| |
| let cleaned = text.trim(); |
| const fenceMatch = cleaned.match(/^```(?:json)?\s*\n?([\s\S]*?)\n?\s*```$/); |
| if (fenceMatch) cleaned = fenceMatch[1].trim(); |
|
|
| try { |
| return JSON.parse(cleaned); |
| } catch (firstError) { |
| |
| const jsonMatch = text.match(/```json\s*([\s\S]*?)\s*```/) || text.match(/```\s*([\s\S]*?)\s*```/); |
| if (jsonMatch && jsonMatch[1]) { |
| try { |
| return JSON.parse(jsonMatch[1].trim()); |
| } catch { } |
| } |
|
|
| |
| const firstBrace = cleaned.indexOf('{'); |
| const lastBrace = cleaned.lastIndexOf('}'); |
| const firstBracket = cleaned.indexOf('['); |
| const lastBracket = cleaned.lastIndexOf(']'); |
|
|
| let start = -1; |
| let end = -1; |
| if (firstBrace !== -1 && (firstBracket === -1 || firstBrace < firstBracket)) { |
| start = firstBrace; |
| end = lastBrace; |
| } else if (firstBracket !== -1) { |
| start = firstBracket; |
| end = lastBracket; |
| } |
|
|
| if (start !== -1 && end !== -1 && end > start) { |
| try { |
| return JSON.parse(cleaned.substring(start, end + 1)); |
| } catch { } |
| } |
|
|
| |
| |
| if (start !== -1) { |
| let partial = cleaned.substring(start, end !== -1 && end > start ? end + 1 : undefined); |
| try { |
| return repairAndParseJSON(partial); |
| } catch { } |
| } |
|
|
| throw firstError; |
| } |
| } |
|
|
| |
| |
| |
| |
| function repairAndParseJSON(raw: string): any { |
| let s = raw; |
|
|
| |
| |
| let inString = false; |
| let escaped = false; |
| let lastGoodIndex = 0; |
|
|
| for (let i = 0; i < s.length; i++) { |
| const ch = s[i]; |
| if (escaped) { escaped = false; continue; } |
| if (ch === '\\') { escaped = true; continue; } |
| if (ch === '"') { |
| inString = !inString; |
| if (!inString) lastGoodIndex = i; |
| } |
| if (!inString) lastGoodIndex = i; |
| } |
|
|
| |
| if (inString) { |
| s = s.substring(0, lastGoodIndex + 1); |
| |
| |
| } |
|
|
| |
| s = s.replace(/,\s*$/, ''); |
|
|
| |
| let braces = 0; |
| let brackets = 0; |
| inString = false; |
| escaped = false; |
| for (let i = 0; i < s.length; i++) { |
| const ch = s[i]; |
| if (escaped) { escaped = false; continue; } |
| if (ch === '\\') { escaped = true; continue; } |
| if (ch === '"') { inString = !inString; continue; } |
| if (inString) continue; |
| if (ch === '{') braces++; |
| else if (ch === '}') braces--; |
| else if (ch === '[') brackets++; |
| else if (ch === ']') brackets--; |
| } |
|
|
| |
| s = s.replace(/,\s*"[^"]*"?\s*:?\s*"?[^"]*$/, ''); |
| s = s.replace(/,\s*$/, ''); |
|
|
| |
| braces = 0; brackets = 0; inString = false; escaped = false; |
| for (let i = 0; i < s.length; i++) { |
| const ch = s[i]; |
| if (escaped) { escaped = false; continue; } |
| if (ch === '\\') { escaped = true; continue; } |
| if (ch === '"') { inString = !inString; continue; } |
| if (inString) continue; |
| if (ch === '{') braces++; |
| else if (ch === '}') braces--; |
| else if (ch === '[') brackets++; |
| else if (ch === ']') brackets--; |
| } |
|
|
| |
| while (brackets > 0) { s += ']'; brackets--; } |
| while (braces > 0) { s += '}'; braces--; } |
|
|
| return JSON.parse(s); |
| } |
|
|