feat: domestic flights, road traffic, CCTV webcams, AI situation brief
Four new intelligence domains for the dashboard: 1. Domestic flights (OpenSky) — global airborne aircraft count by region with commercial/general breakdown. No API key needed. 2. Road traffic (TomTom) — real-time congestion % for 20 major world cities + traffic incidents in 5 strategic regions. Needs TOMTOM_API_KEY (free 2500 req/day at developer.tomtom.com). 3. CCTV webcams (Windy) — public traffic camera locations worldwide. Needs WINDY_API_KEY (free 100 req/day at api.windy.com). 4. AI situation brief (Ollama) — LLM-generated 3-paragraph intelligence brief synthesizing all dashboard data. Uses local Ollama (llama3.2). Falls back to structured metrics summary. New files: sources/traffic.py, sources/webcams.py, analysis/situation.py Modified: sources/aviation.py (+fetch_domestic_flights), dashboard/app.py, dashboard/index.html (drawer sections + HUD pills for all 4 domains). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
fc105872e2
commit
fcc702b093
@@ -41,10 +41,13 @@ from world_intel_mcp.sources import (
|
||||
social,
|
||||
nuclear,
|
||||
service_status,
|
||||
traffic,
|
||||
webcams,
|
||||
)
|
||||
from world_intel_mcp.analysis.alerts import fetch_alert_digest, fetch_weekly_trends
|
||||
from world_intel_mcp.analysis.posture import fetch_strategic_posture
|
||||
from world_intel_mcp.analysis.exposure import fetch_population_exposure
|
||||
from world_intel_mcp.analysis.situation import fetch_situation_brief
|
||||
from world_intel_mcp.sources.fleet import fetch_fleet_report
|
||||
from world_intel_mcp.config.countries import INTEL_HOTSPOTS, STRATEGIC_WATERWAYS
|
||||
from world_intel_mcp.config.geospatial import MILITARY_BASES, STRATEGIC_PORTS, PIPELINES, NUCLEAR_FACILITIES
|
||||
@@ -115,6 +118,10 @@ async def _fetch_overview() -> dict:
|
||||
"strategic_posture": fetch_strategic_posture(fetcher),
|
||||
"fleet_report": fetch_fleet_report(fetcher),
|
||||
"population_exposure": fetch_population_exposure(fetcher),
|
||||
"domestic_flights": aviation.fetch_domestic_flights(fetcher),
|
||||
"traffic_flow": traffic.fetch_traffic_flow(fetcher),
|
||||
"traffic_incidents": traffic.fetch_traffic_incidents(fetcher),
|
||||
"webcams": webcams.fetch_webcams(fetcher),
|
||||
}
|
||||
|
||||
# Per-coro timeout so no single slow source blocks the entire dashboard.
|
||||
@@ -183,6 +190,15 @@ async def _fetch_overview() -> dict:
|
||||
"count": len(CABLE_CORRIDORS),
|
||||
}
|
||||
|
||||
# AI situational brief (runs after main gather so it has all data)
|
||||
try:
|
||||
result["situation_brief"] = await asyncio.wait_for(
|
||||
fetch_situation_brief(result), timeout=35.0,
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.warning("Situation brief failed: %s", exc)
|
||||
result["situation_brief"] = {"error": str(exc)}
|
||||
|
||||
# Attach source health + timestamp
|
||||
result["source_health"] = _breaker.status() if _breaker else {}
|
||||
result["cache_stats"] = _cache.stats() if _cache else {}
|
||||
|
||||
Reference in New Issue
Block a user