import json
import re

_FENCE_RE = re.compile(r"^```(?:json)?\s*|\s*```$", re.MULTILINE)
_OBJECT_RE = re.compile(r"\{.*\}", re.DOTALL)


def parse_json_response(text: str) -> dict:
    """Parse a model's raw text output as a JSON object, tolerating the two ways
    models routinely violate "JSON only": wrapping the object in a ```json fence, or
    prefacing/trailing it with a sentence of commentary.

    Not every provider supports a strict JSON-only response mode (OpenAI's
    response_format does; Anthropic and local Ollama models rely on the system prompt
    alone), so every provider implementation runs its output through this rather than
    calling json.loads directly.
    """
    cleaned = _FENCE_RE.sub("", text.strip()).strip()
    try:
        return json.loads(cleaned)
    except json.JSONDecodeError:
        match = _OBJECT_RE.search(cleaned)
        if not match:
            raise
        return json.loads(match.group(0))
