""" Category lookups for topic_metadata.json. Used by the router to resolve "compare this with other X" style queries that reference the previous topic implicitly, without naming a second topic explicitly (e.g. "compare BFS with other graph algorithms"). """ import json import os import config from logs.logger import get_logger logger = get_logger(__name__) _metadata_cache = None def _load_metadata() -> dict: global _metadata_cache if _metadata_cache is None: if not os.path.exists(config.TOPIC_METADATA_PATH): logger.warning("topic_metadata.json not found; category lookups disabled.") _metadata_cache = {} else: with open(config.TOPIC_METADATA_PATH, "r", encoding="utf-8") as f: _metadata_cache = json.load(f) return _metadata_cache def get_category(topic_name: str) -> str | None: """Returns the category string for a canonical topic name, or None.""" for entry in _load_metadata().values(): if entry.get("topic") == topic_name: return entry.get("category") return None def get_sibling_topics(topic_name: str, exclude: list = None, limit: int = 2) -> list: """ Returns up to `limit` other topic names sharing the same category as `topic_name` (e.g. siblings of "Breadth-First Search" in category "Graph Traversal" -> ["Depth-First Search", "Dijkstra's Algorithm"]). """ exclude = set(exclude or []) | {topic_name} category = get_category(topic_name) if not category: return [] siblings = [ entry["topic"] for entry in _load_metadata().values() if entry.get("category") == category and entry.get("topic") not in exclude ] return siblings[:limit]