Parse an LLM page response into a single JSON object. Unwraps a single-element ``[{...}]`` array (some models wrap the object in a list). Returns ``None`` when the response is valid JSON of the wrong shape (empty/multi-element array, list of scalars) so callers skip the page rather
(text: str)
| 532 | |
| 533 | |
| 534 | def _parse_page_json(text: str) -> dict | None: |
| 535 | """Parse an LLM page response into a single JSON object. |
| 536 | |
| 537 | Unwraps a single-element ``[{...}]`` array (some models wrap the object in |
| 538 | a list). Returns ``None`` when the response is valid JSON of the wrong |
| 539 | shape (empty/multi-element array, list of scalars) so callers skip the page |
| 540 | rather than persisting the raw JSON text as its body. Propagates the |
| 541 | json/ValueError from ``_parse_json`` when the text isn't JSON at all, which |
| 542 | callers catch to fall back to treating ``raw`` as a prose-markdown body. |
| 543 | """ |
| 544 | parsed = _parse_json(text) |
| 545 | if isinstance(parsed, list) and len(parsed) == 1 and isinstance(parsed[0], dict): |
| 546 | parsed = parsed[0] |
| 547 | return parsed if isinstance(parsed, dict) else None |
| 548 | |
| 549 | |
| 550 | def _page_fields(raw: str) -> tuple[str, str, dict | None]: |