"""名词解释服务。 从 assets/glossary.json 读取词条,按 key/display/category 查询。 不做 LLM 生成,纯静态数据查询。 """ from __future__ import annotations import json from typing import Any, Optional from util.constants import SKILL_SLUG from util.logging_config import get_skill_logger from util.runtime_paths import get_skill_root log = get_skill_logger() def _load_glossary() -> list[dict[str, Any]]: """从 assets/glossary.json 加载全部词条。""" glossary_path = get_skill_root() / "assets" / "glossary.json" try: with open(glossary_path, "r", encoding="utf-8") as f: data = json.load(f) terms = data.get("terms", []) if isinstance(data, dict) else [] return terms if isinstance(terms, list) else [] except (FileNotFoundError, json.JSONDecodeError, OSError): return [] def explain_term(term: str) -> dict[str, Any]: """查询单个名词解释。 支持按 key(精确)或 display(包含)匹配。 未命中返回结构化空(ok=True, found=False)。 """ log.info("glossary_explain term=%s", term) terms = _load_glossary() term_lower = (term or "").strip().lower() hit: Optional[dict[str, Any]] = None for t in terms: if str(t.get("key", "")).lower() == term_lower: hit = t break if term_lower in str(t.get("display", "")).lower(): hit = t break if hit is None: return { "ok": True, "skill": SKILL_SLUG, "found": False, "term": term, "explanation": None, "suggestions": [str(t.get("display", "")) for t in terms[:5]], } return { "ok": True, "skill": SKILL_SLUG, "found": True, "term": term, "key": hit.get("key"), "display": hit.get("display"), "category": hit.get("category"), "explanation": hit.get("explanation"), "example": hit.get("example"), } def list_terms(category: str | None = None) -> dict[str, Any]: """列出全部或按分类的词条。""" terms = _load_glossary() if category: filtered = [t for t in terms if str(t.get("category", "")).lower() == category.lower()] else: filtered = terms return { "ok": True, "skill": SKILL_SLUG, "count": len(filtered), "categories": sorted({str(t.get("category", "")) for t in terms}), "terms": [ { "key": t.get("key"), "display": t.get("display"), "category": t.get("category"), "explanation": t.get("explanation"), "example": t.get("example"), } for t in filtered ], }