| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- from __future__ import annotations
- import json
- import os
- import subprocess
- from functools import lru_cache
- from typing import Any
- from news_mcp.entity_normalize import normalize_entity
- @lru_cache(maxsize=1024)
- def resolve_entity_via_trends(entity: str) -> dict[str, Any]:
- """Resolve a normalized entity through trends-mcp, falling back cleanly.
- The input is normalized first using the same local normalization rules used
- everywhere else in news-mcp, so query and storage paths stay aligned.
- """
- normalized = normalize_entity(entity)
- if not normalized:
- return {
- "raw": entity,
- "normalized": "",
- "canonical_label": "",
- "mid": None,
- "type": None,
- "source": "empty",
- }
- config = os.getenv("MCPORTER_CONFIG", os.path.expanduser("~/.openclaw/workspace/config/mcporter.json"))
- command = [
- "mcporter",
- "--config",
- config,
- "call",
- "trends.resolve_entity",
- f"keyword={normalized}",
- ]
- try:
- proc = subprocess.run(command, capture_output=True, text=True, timeout=20, check=False)
- if proc.returncode == 0 and proc.stdout.strip():
- payload = json.loads(proc.stdout)
- return {
- "raw": entity,
- "normalized": normalized,
- "canonical_label": payload.get("canonical_label") or normalized,
- "mid": payload.get("mid"),
- "type": payload.get("type"),
- "candidates": payload.get("candidates", []),
- "source": "trends-mcp",
- }
- except Exception:
- pass
- # Conservative fallback: keep the local normalized form and leave MID unset.
- return {
- "raw": entity,
- "normalized": normalized,
- "canonical_label": normalized,
- "mid": None,
- "type": None,
- "source": "fallback",
- }
|