{"version":3,"file":"extractJSON.mjs","names":[],"sources":["../../../src/utils/extractJSON.ts"],"sourcesContent":["/**\n * Extracts and parses the first valid JSON value (object or array) from a string containing arbitrary text.\n * This is used to safely extract JSON from LLM responses that may contain additional text or markdown.\n *\n * @example\n * // Extracts JSON object from markdown response:\n * ```json\n * {\n *   \"title\": \"Test content declarations\",\n *   \"description\": \"A comprehensive test dictionary...\",\n *   \"tags\": [\"test tag\"]\n * }\n * ```\n *\n * @example\n * // Extracts JSON array:\n * ```json\n * [\"item1\", \"item2\", \"item3\"]\n * ```\n *\n * @example\n * // Extracts JSON from markdown:\n * Here is the response:\n * ```json\n * {\"key\": \"value\"}\n * ```\n * End of response.\n *\n * @throws {Error} If no valid JSON object/array is found or if parsing fails\n * @returns {T} The parsed JSON value cast to type T\n */\nexport const extractJson = <T = any>(input: string): T => {\n  const opening = input.match(/[{[]/);\n  if (!opening) throw new Error('No JSON start character ({ or [) found.');\n\n  const startIdx = opening.index!;\n  const openChar = input[startIdx];\n  const closeChar = openChar === '{' ? '}' : ']';\n\n  let depth = 0;\n  let inString = false;\n  let escaped = false;\n\n  for (let i = startIdx; i < input.length; i++) {\n    const char = input[i];\n\n    if (escaped) {\n      escaped = false;\n      continue;\n    }\n\n    if (char === '\\\\') {\n      escaped = true;\n      continue;\n    }\n\n    if (char === '\"') {\n      inString = !inString;\n      continue;\n    }\n\n    if (!inString) {\n      if (char === openChar) {\n        depth++;\n      } else if (char === closeChar) {\n        depth--;\n        if (depth === 0) {\n          const jsonSubstring = input.slice(startIdx, i + 1);\n          try {\n            return JSON.parse(jsonSubstring) as T;\n          } catch (err) {\n            throw new Error(`Failed to parse JSON: ${(err as Error).message}`);\n          }\n        }\n      }\n    }\n  }\n\n  throw new Error('Reached end of input without closing JSON bracket.');\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAa,eAAwB,UAAqB;CACxD,MAAM,UAAU,MAAM,MAAM,OAAO;AACnC,KAAI,CAAC,QAAS,OAAM,IAAI,MAAM,0CAA0C;CAExE,MAAM,WAAW,QAAQ;CACzB,MAAM,WAAW,MAAM;CACvB,MAAM,YAAY,aAAa,MAAM,MAAM;CAE3C,IAAI,QAAQ;CACZ,IAAI,WAAW;CACf,IAAI,UAAU;AAEd,MAAK,IAAI,IAAI,UAAU,IAAI,MAAM,QAAQ,KAAK;EAC5C,MAAM,OAAO,MAAM;AAEnB,MAAI,SAAS;AACX,aAAU;AACV;;AAGF,MAAI,SAAS,MAAM;AACjB,aAAU;AACV;;AAGF,MAAI,SAAS,MAAK;AAChB,cAAW,CAAC;AACZ;;AAGF,MAAI,CAAC,UACH;OAAI,SAAS,SACX;YACS,SAAS,WAAW;AAC7B;AACA,QAAI,UAAU,GAAG;KACf,MAAM,gBAAgB,MAAM,MAAM,UAAU,IAAI,EAAE;AAClD,SAAI;AACF,aAAO,KAAK,MAAM,cAAc;cACzB,KAAK;AACZ,YAAM,IAAI,MAAM,yBAA0B,IAAc,UAAU;;;;;;AAO5E,OAAM,IAAI,MAAM,qDAAqD"}