Spaces:
Sleeping
Sleeping
| """ | |
| TemplateService β Reads template metadata and prompts from backend/templates/. | |
| All template-specific logic lives in meta.json and prompt.md. This service | |
| is template-agnostic: it discovers templates from the registry and reads | |
| their files. Unknown IDs fall back to "default". | |
| """ | |
| import json | |
| import os | |
| from pathlib import Path | |
| from typing import Any | |
| # Path to backend/templates/ (relative to this file: app/services/template_service.py) | |
| _TEMPLATES_DIR = Path(__file__).resolve().parent.parent.parent / "templates" | |
| def _load_registry() -> list[str]: | |
| """Load template IDs from registry.json.""" | |
| path = _TEMPLATES_DIR / "registry.json" | |
| if not path.exists(): | |
| return ["default"] | |
| with open(path, encoding="utf-8") as f: | |
| data = json.load(f) | |
| return data if isinstance(data, list) else ["default"] | |
| def _load_meta(template_id: str) -> dict[str, Any] | None: | |
| """Load meta.json for a template. Returns None if not found.""" | |
| path = _TEMPLATES_DIR / template_id / "meta.json" | |
| if not path.exists(): | |
| return None | |
| with open(path, encoding="utf-8") as f: | |
| return json.load(f) | |
| def _load_prompt(template_id: str) -> str: | |
| """Load prompt.md content for a template. Returns empty string if not found.""" | |
| path = _TEMPLATES_DIR / template_id / "prompt.md" | |
| if not path.exists(): | |
| return "" | |
| with open(path, encoding="utf-8") as f: | |
| return f.read() | |
| # βββ Public API βββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def list_templates() -> list[dict[str, Any]]: | |
| """Return list of all templates (meta for each).""" | |
| registry = _load_registry() | |
| result = [] | |
| for tid in registry: | |
| meta = _load_meta(tid) | |
| if meta: | |
| result.append(meta) | |
| return result | |
| def get_meta(template_id: str) -> dict[str, Any] | None: | |
| """Get meta.json for one template.""" | |
| return _load_meta(template_id) | |
| def get_prompt(template_id: str) -> str: | |
| """Get prompt.md content for one template. Reads fresh on each call.""" | |
| return _load_prompt(template_id) | |
| def get_valid_layouts(template_id: str) -> set[str]: | |
| """Get the set of valid layout IDs for a template.""" | |
| meta = _load_meta(template_id) | |
| if not meta: | |
| return set() | |
| layouts = meta.get("valid_layouts", []) | |
| return set(layouts) if isinstance(layouts, list) else set() | |
| def get_hero_layout(template_id: str) -> str: | |
| """Get the hero layout ID (scene 0). Default: hero_image.""" | |
| meta = _load_meta(template_id) | |
| if not meta: | |
| return "hero_image" | |
| return meta.get("hero_layout", "hero_image") | |
| def get_fallback_layout(template_id: str) -> str: | |
| """Get the fallback layout when DSPy output is invalid.""" | |
| meta = _load_meta(template_id) | |
| if not meta: | |
| return "text_narration" | |
| return meta.get("fallback_layout", "text_narration") | |
| def get_composition_id(template_id: str) -> str: | |
| """Get the Remotion composition ID for rendering.""" | |
| meta = _load_meta(template_id) | |
| if not meta: | |
| return "DefaultVideo" | |
| return meta.get("composition_id", "DefaultVideo") | |
| def get_image_layout(template_id: str) -> str | None: | |
| """Get the layout ID for image-heavy scenes (blog images). None = no override.""" | |
| meta = _load_meta(template_id) | |
| if not meta: | |
| return None | |
| return meta.get("image_layout") | |
| def get_preview_colors(template_id: str) -> dict[str, str] | None: | |
| """Get preview_colors (accent, bg, text) for template. None = use request defaults.""" | |
| meta = _load_meta(template_id) | |
| if not meta: | |
| return None | |
| pc = meta.get("preview_colors") | |
| if not isinstance(pc, dict): | |
| return None | |
| return pc | |
| def validate_template_id(template_id: str | None) -> str: | |
| """Return template_id if valid, else 'default'.""" | |
| if not template_id or not isinstance(template_id, str): | |
| return "default" | |
| tid = template_id.strip().lower() | |
| registry = _load_registry() | |
| if tid in registry: | |
| return tid | |
| return "default" | |