""" Load LLM documentation for form generation. Direct only — no URL reading. Uses embedded built-in docs (fast) or optional local JSON file. No network calls. """ import json import logging import os import time from pathlib import Path from typing import Any, Dict, Optional from .builtin_docs import BUILTIN_DOCS logger = logging.getLogger(__name__) _DOCS_CACHE: Optional[Dict[str, Any]] = None _CACHE_TIME: float = 0 _DOCS_TTL_SECONDS = 3600 # 1 hour for file; built-in is effectively permanent def _get_docs_json_path() -> Optional[Path]: path = os.getenv("DOCS_JSON_PATH") if path: p = Path(path) return p if p.is_absolute() else Path(__file__).resolve().parent.parent / path default = Path(__file__).resolve().parent / "llm_docs.json" return default if default.exists() else None def fetch_docs( include_examples: bool = True, include_conditional_logic: bool = True, include_ai_fields: bool = True, force_refresh: bool = False, ) -> Dict[str, Any]: """ Return LLM documentation. No URL fetch — uses local file if present, else built-in docs. Always returns a dict (built-in docs at minimum) so context packs are always available. """ global _DOCS_CACHE, _CACHE_TIME now = time.time() if not force_refresh and _DOCS_CACHE is not None and (now - _CACHE_TIME) < _DOCS_TTL_SECONDS: return _DOCS_CACHE docs_path = _get_docs_json_path() if docs_path: try: with open(docs_path, "r", encoding="utf-8") as f: docs = json.load(f) if isinstance(docs, dict): _DOCS_CACHE = docs _CACHE_TIME = now logger.info("Loaded docs from file %s (version=%s)", docs_path, docs.get("version")) return docs except Exception as e: logger.warning("Failed to load docs from %s: %s", docs_path, e) _DOCS_CACHE = BUILTIN_DOCS _CACHE_TIME = now logger.debug("Using built-in docs (version=%s)", BUILTIN_DOCS.get("version")) return BUILTIN_DOCS