|
|
@@ -106,7 +106,7 @@ NEWS_TOOL_CARDS = [
|
|
|
"get_latest_events",
|
|
|
"Get the newest deduplicated clusters for a topic or resolved entity-like query.",
|
|
|
[
|
|
|
- {"name": "topic", "type": "string", "default": "crypto", "meaning": "coarse category or entity-like topic"},
|
|
|
+ {"name": "topic", "type": "string", "default": "all topics", "meaning": "coarse category (crypto, macro, regulation, ai, other), entity-like topic, or omit for all topics"},
|
|
|
{"name": "limit", "type": "integer", "default": 5, "range": "1-20"},
|
|
|
{"name": "include_articles", "type": "boolean", "default": False},
|
|
|
],
|
|
|
@@ -174,7 +174,7 @@ NEWS_COMPOSITION_RECIPES = [
|
|
|
"get_latest_events(topic=...)",
|
|
|
"optionally get_event_summary(event_id=...) for the strongest cluster",
|
|
|
],
|
|
|
- "notes": ["Best for a quick tail of what is happening now."]
|
|
|
+ "notes": ["Best for a quick tail of what is happening now. Omit topic for all topics, or pass crypto/macro/regulation/ai/other to filter."]
|
|
|
},
|
|
|
{
|
|
|
"name": "entity-deep-dive",
|
|
|
@@ -250,14 +250,16 @@ NEWS_EXAMPLE_CHAINS = [
|
|
|
|
|
|
|
|
|
@mcp.tool(description="Investigate a topic and return the newest deduplicated news clusters, sorted by recency.")
|
|
|
-async def get_latest_events(topic: str = "crypto", limit: int = 5, include_articles: bool = False):
|
|
|
+async def get_latest_events(topic: str | None = None, limit: int = 5, include_articles: bool = False):
|
|
|
limit = max(1, min(int(limit), 20))
|
|
|
- # If the caller passes an entity-like value, resolve it and use the canonical
|
|
|
- # entity as the query lens. Otherwise keep the original topic path.
|
|
|
- topic_norm = normalize_query(topic).lower()
|
|
|
- resolved = resolve_entity_via_trends(topic_norm)
|
|
|
+ # When topic is omitted, search across all topics (no topic filter).
|
|
|
+ # When topic is provided and matches a known topic, filter by that topic.
|
|
|
+ # Otherwise treat the value as an entity-like query.
|
|
|
+ topic_norm = normalize_query(topic).lower() if topic else ""
|
|
|
+ resolved = resolve_entity_via_trends(topic_norm) if topic_norm else {}
|
|
|
allowed = {t.lower() for t in DEFAULT_TOPICS}
|
|
|
is_topic = topic_norm in allowed
|
|
|
+ is_all_topics = not topic_norm
|
|
|
query_terms = {
|
|
|
topic_norm,
|
|
|
str(resolved.get("normalized") or "").strip().lower(),
|
|
|
@@ -268,7 +270,10 @@ async def get_latest_events(topic: str = "crypto", limit: int = 5, include_artic
|
|
|
|
|
|
store = SQLiteClusterStore(DB_PATH)
|
|
|
|
|
|
- if is_topic:
|
|
|
+ if is_all_topics:
|
|
|
+ # No topic specified: return freshest clusters across all topics.
|
|
|
+ clusters = store.get_latest_clusters_all_topics(ttl_hours=DEFAULT_LOOKBACK_HOURS, limit=limit)
|
|
|
+ elif is_topic:
|
|
|
# Cache-first: only refresh if we currently have no fresh clusters for this topic.
|
|
|
clusters = store.get_latest_clusters(topic=topic_norm, ttl_hours=DEFAULT_LOOKBACK_HOURS, limit=limit)
|
|
|
if not clusters:
|