|
|
|
|
|
import re |
|
|
from typing import Optional |
|
|
|
|
|
def safe_truncate(text: str, max_chars: int = 12000) -> str: |
|
|
if not text: |
|
|
return "" |
|
|
return text if len(text) <= max_chars else text[:max_chars] + "\n\n[[TRUNCATED]]" |
|
|
|
|
|
def sanitize_text(text: Optional[str]) -> str: |
|
|
if not text: |
|
|
return "" |
|
|
t = re.sub(r"<[^>]+>", " ", text) |
|
|
t = re.sub(r"\s+", " ", t).strip() |
|
|
return t |
|
|
|
|
|
def _extract_json_from_text(text: str) -> Optional[str]: |
|
|
if not text: |
|
|
return None |
|
|
start = None |
|
|
depth = 0 |
|
|
for i, ch in enumerate(text): |
|
|
if ch == "{": |
|
|
if start is None: |
|
|
start = i |
|
|
depth += 1 |
|
|
elif ch == "}": |
|
|
if depth > 0: |
|
|
depth -= 1 |
|
|
if depth == 0 and start is not None: |
|
|
return text[start:i+1] |
|
|
return None |
|
|
|