File size: 1,596 Bytes
2312199
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
"""Shared utility functions."""

from __future__ import annotations

import json

_JSON_DECODER = json.JSONDecoder()


def load_card_database():
    """Load the structured card database from data/card_database.json."""
    from lexenvs.config import project_root
    from lexenvs.schemas.card_database import CardDatabase

    db_path = project_root() / "data" / "card_database.json"
    if not db_path.exists():
        return None
    db_json = json.loads(db_path.read_text(encoding="utf-8"))
    return CardDatabase(**db_json)


def extract_json_block(text: str) -> dict | None:  # type: ignore[type-arg]
    """Extract the first JSON object from text.

    Looks for ```json ... ``` fenced blocks first, then scans for
    the first valid JSON object using the stdlib decoder.
    """
    # Try fenced code block via string splitting
    marker = "```json"
    start = text.find(marker)
    if start != -1:
        inner_start = text.index("\n", start) + 1
        end = text.find("```", inner_start)
        if end != -1:
            try:
                return json.loads(text[inner_start:end])  # type: ignore[no-any-return]
            except json.JSONDecodeError:
                pass

    # Scan for the first raw JSON object using raw_decode
    decoder = _JSON_DECODER
    idx = text.find("{")
    while idx != -1:
        try:
            obj, _ = decoder.raw_decode(text, idx)
            if isinstance(obj, dict):
                return obj  # type: ignore[no-any-return]
        except json.JSONDecodeError:
            pass
        idx = text.find("{", idx + 1)

    return None