import type { AgentId, DataSourceSpec, SourceDelivery } from "./types"; function rssSource(spec: { id: string; agentId: AgentId; delivery: SourceDelivery; name: string; url: string; allowlistStatus: DataSourceSpec["allowlistStatus"]; tags: string[]; rationale: string; notes?: string; }): DataSourceSpec { return { id: spec.id, agentId: spec.agentId, delivery: spec.delivery, name: spec.name, kind: "rss", endpoint: { kind: "url", url: spec.url, }, auth: "none", allowlistStatus: spec.allowlistStatus, tags: spec.tags, rationale: spec.rationale, notes: spec.notes, }; } function scrapeSource(spec: { id: string; agentId: AgentId; delivery: SourceDelivery; name: string; url: string; auth?: DataSourceSpec["auth"]; allowlistStatus: DataSourceSpec["allowlistStatus"]; tags: string[]; rationale: string; notes?: string; }): DataSourceSpec { return { id: spec.id, agentId: spec.agentId, delivery: spec.delivery, name: spec.name, kind: "scrape", endpoint: { kind: "url", url: spec.url, }, auth: spec.auth ?? "none", allowlistStatus: spec.allowlistStatus, tags: spec.tags, rationale: spec.rationale, notes: spec.notes, }; } function worldMonitorSource(spec: { id: string; agentId: AgentId; delivery: SourceDelivery; name: string; rpc: string; selector?: string; kind?: Extract; auth?: DataSourceSpec["auth"]; tags: string[]; rationale: string; notes?: string; }): DataSourceSpec { return { id: spec.id, agentId: spec.agentId, delivery: spec.delivery, name: spec.name, kind: spec.kind ?? "structured", endpoint: { kind: "worldmonitor", rpc: spec.rpc, ...(spec.selector ? { selector: spec.selector } : {}), }, auth: spec.auth ?? "none", allowlistStatus: "external", tags: spec.tags, rationale: spec.rationale, notes: spec.notes, }; } function telegramSource(spec: { id: string; agentId: AgentId; delivery: SourceDelivery; name: string; handle: string; tags: string[]; rationale: string; notes?: string; }): DataSourceSpec { return { id: spec.id, agentId: spec.agentId, delivery: spec.delivery, name: spec.name, kind: "telegram", endpoint: { kind: "telegram", handle: spec.handle, }, auth: "session", allowlistStatus: "not_applicable", tags: spec.tags, rationale: spec.rationale, notes: spec.notes, }; } function videoSource(spec: { id: string; agentId: AgentId; delivery: SourceDelivery; name: string; channel: string; tags: string[]; rationale: string; notes?: string; }): DataSourceSpec { return { id: spec.id, agentId: spec.agentId, delivery: spec.delivery, name: spec.name, kind: "video", endpoint: { kind: "video", channel: spec.channel, }, auth: "none", allowlistStatus: "not_applicable", tags: spec.tags, rationale: spec.rationale, notes: spec.notes, }; } function googleNewsSearchUrl(query: string): string { return `https://news.google.com/rss/search?q=${encodeURIComponent(query)}&hl=en-US&gl=US&ceid=US:en`; } const FALLBACK_QUERY_NOTE = "Uses a Google News site-query fallback because the direct publisher or government endpoint is blocked, dead, or non-RSS."; const sources: DataSourceSpec[] = [ rssSource({ id: "us-reuters-us", agentId: "us", delivery: "training_core", name: "Reuters US", url: "https://news.google.com/rss/search?q=site:reuters.com+US&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["us", "wire", "domestic"], rationale: "Wire-grade US political and federal reporting for fast state reaction and domestic fallout.", }), rssSource({ id: "us-politico", agentId: "us", delivery: "training_core", name: "Politico", url: "https://rss.politico.com/politics-news.xml", allowlistStatus: "allowed", tags: ["us", "politics", "coalitions"], rationale: "Captures executive maneuvering, Hill dynamics, and coalition signaling.", }), rssSource({ id: "us-wsj", agentId: "us", delivery: "training_core", name: "Wall Street Journal", url: "https://feeds.content.dowjones.io/public/rss/RSSUSnews", allowlistStatus: "allowed", tags: ["us", "markets", "elite-policy"], rationale: "Business and policy-elite framing relevant to backlash, oil, and market stress.", }), rssSource({ id: "us-white-house", agentId: "us", delivery: "training_core", name: "White House", url: "https://news.google.com/rss/search?q=site:whitehouse.gov&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["us", "official", "executive"], rationale: "Official executive posture and public messaging.", }), rssSource({ id: "us-state-dept", agentId: "us", delivery: "training_core", name: "State Dept", url: "https://news.google.com/rss/search?q=site:state.gov+OR+%22State+Department%22&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["us", "official", "diplomacy"], rationale: "Diplomatic posture, sanctions posture, and alliance language.", }), rssSource({ id: "us-usni-news", agentId: "us", delivery: "training_core", name: "USNI News", url: "https://news.usni.org/feed", allowlistStatus: "allowed", tags: ["us", "naval", "centcom"], rationale: "Naval deployments and fleet posture relevant to US deterrence and force signaling.", }), worldMonitorSource({ id: "us-polymarket", agentId: "us", delivery: "training_core", name: "Polymarket Geopolitical Markets", rpc: "prediction/v1/list-prediction-markets", selector: "geopolitics", auth: "relay", tags: ["us", "prediction", "public-expectations"], rationale: "Crowd-implied escalation and political-risk signal.", }), videoSource({ id: "us-fox-live", agentId: "us", delivery: "live_demo", name: "Fox News Live", channel: "@FoxNews", tags: ["us", "live", "media"], rationale: "Domestic reaction and media pulse during live sessions.", }), videoSource({ id: "us-washington-webcam", agentId: "us", delivery: "live_demo", name: "Washington DC Webcam", channel: "@AxisCommunications", tags: ["us", "live", "webcam"], rationale: "Ambient visual context from the US capital during demos.", }), rssSource({ id: "us-npr-news", agentId: "us", delivery: "training_core", name: "NPR News", url: "https://feeds.npr.org/1001/rss.xml", allowlistStatus: "allowed", tags: ["us", "public-media", "domestic"], rationale: "Broad US domestic pulse that captures public-facing political and social fallout.", }), rssSource({ id: "us-pentagon", agentId: "us", delivery: "training_core", name: "Pentagon", url: "https://news.google.com/rss/search?q=site:defense.gov+OR+Pentagon&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["us", "official", "defense"], rationale: "Official defense posture, deployments, and deterrence messaging.", }), rssSource({ id: "us-treasury", agentId: "us", delivery: "training_core", name: "Treasury", url: "https://news.google.com/rss/search?q=site:treasury.gov+OR+%22Treasury+Department%22&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["us", "official", "sanctions"], rationale: "Tracks sanctions posture, financial coercion, and macro-stability messaging.", }), rssSource({ id: "us-federal-reserve", agentId: "us", delivery: "training_core", name: "Federal Reserve", url: "https://www.federalreserve.gov/feeds/press_all.xml", allowlistStatus: "allowed", tags: ["us", "official", "rates"], rationale: "Monetary-policy signaling and emergency liquidity posture.", }), rssSource({ id: "us-sec", agentId: "us", delivery: "training_core", name: "SEC", url: "https://www.sec.gov/news/pressreleases.rss", allowlistStatus: "allowed", tags: ["us", "official", "markets"], rationale: "Market-integrity and disclosure signals during crisis-driven volatility.", }), rssSource({ id: "us-defense-one", agentId: "us", delivery: "training_core", name: "Defense One", url: "https://www.defenseone.com/rss/all/", allowlistStatus: "allowed", tags: ["us", "defense", "analysis"], rationale: "Civil-military analysis and Pentagon ecosystem reporting.", }), rssSource({ id: "us-defense-news", agentId: "us", delivery: "training_core", name: "Defense News", url: "https://www.defensenews.com/arc/outboundfeeds/rss/?outputType=xml", allowlistStatus: "allowed", tags: ["us", "defense", "industry"], rationale: "Operational and defense-industrial coverage tied to force readiness.", }), rssSource({ id: "us-military-times", agentId: "us", delivery: "training_core", name: "Military Times", url: "https://www.militarytimes.com/arc/outboundfeeds/rss/?outputType=xml", allowlistStatus: "allowed", tags: ["us", "military", "personnel"], rationale: "Troop, veteran, and force-posture reporting relevant to domestic military sentiment.", }), videoSource({ id: "us-abc-news-live", agentId: "us", delivery: "live_demo", name: "ABC News Live", channel: "@ABCNews", tags: ["us", "live", "media"], rationale: "Additional US broadcast-news reaction during live sessions.", }), videoSource({ id: "us-cbs-news-live", agentId: "us", delivery: "live_demo", name: "CBS News Live", channel: "@CBSNews", tags: ["us", "live", "media"], rationale: "Mainstream TV framing and breaking-event cadence for demos.", }), videoSource({ id: "us-nbc-news-live", agentId: "us", delivery: "live_demo", name: "NBC News Live", channel: "@NBCNews", tags: ["us", "live", "media"], rationale: "Broad domestic coverage lane for live domestic sentiment tracking.", }), worldMonitorSource({ id: "israel-oref", agentId: "israel", delivery: "training_core", name: "OREF Rocket Alerts", rpc: "military/v1/list-oref-alerts", auth: "relay", tags: ["israel", "sirens", "air-defense"], rationale: "Highest-signal direct warning source for rockets, missiles, and drones.", }), rssSource({ id: "israel-haaretz", agentId: "israel", delivery: "training_core", name: "Haaretz", url: "https://news.google.com/rss/search?q=site:haaretz.com+when:7d&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["israel", "security", "local-reporting"], rationale: "Israeli political-security reporting with local context.", }), rssSource({ id: "israel-pm-office", agentId: "israel", delivery: "training_core", name: "PM Office", url: googleNewsSearchUrl('site:gov.il/en "Prime Minister\'s Office" Israel'), allowlistStatus: "allowed", tags: ["israel", "official", "executive"], rationale: "Prime minister messaging, cabinet posture, and official crisis framing.", notes: FALLBACK_QUERY_NOTE, }), rssSource({ id: "israel-idf-spokesman", agentId: "israel", delivery: "training_core", name: "IDF Spokesman", url: googleNewsSearchUrl('site:idf.il/en IDF spokesperson Israel'), allowlistStatus: "allowed", tags: ["israel", "official", "military"], rationale: "Official military announcements, strike claims, and force-posture messaging.", notes: FALLBACK_QUERY_NOTE, }), rssSource({ id: "israel-mfa-israel", agentId: "israel", delivery: "training_core", name: "MFA Israel", url: googleNewsSearchUrl('site:mfa.gov.il Israel Ministry of Foreign Affairs'), allowlistStatus: "allowed", tags: ["israel", "official", "diplomacy"], rationale: "Diplomatic posture, international signaling, and formal foreign-ministry messaging.", notes: FALLBACK_QUERY_NOTE, }), rssSource({ id: "israel-knesset", agentId: "israel", delivery: "training_core", name: "Knesset", url: googleNewsSearchUrl('site:main.knesset.gov.il/en Knesset Israel'), allowlistStatus: "allowed", tags: ["israel", "official", "legislature"], rationale: "Legislative moves, emergency authorities, and coalition-fracture signals.", notes: FALLBACK_QUERY_NOTE, }), rssSource({ id: "israel-bank-of-israel", agentId: "israel", delivery: "training_core", name: "Bank of Israel", url: googleNewsSearchUrl('site:boi.org.il/en "Bank of Israel"'), allowlistStatus: "allowed", tags: ["israel", "official", "economy"], rationale: "Macro-financial stress, monetary posture, and economic-stability signaling.", notes: FALLBACK_QUERY_NOTE, }), worldMonitorSource({ id: "israel-opensky-flights", agentId: "israel", delivery: "training_core", name: "OpenSky Military Flights", rpc: "military/v1/list-military-flights", selector: "opensky", auth: "relay", tags: ["israel", "airspace", "opensky"], rationale: "Airspace and sortie activity tied to Israeli operational tempo.", }), worldMonitorSource({ id: "israel-wingbits-enrichment", agentId: "israel", delivery: "training_core", name: "Wingbits Flight Enrichment", rpc: "military/v1/list-military-flights", selector: "wingbits", auth: "relay", tags: ["israel", "airspace", "wingbits"], rationale: "Adds operator and aircraft context for military-flight interpretation.", }), worldMonitorSource({ id: "israel-tlv-notam", agentId: "israel", delivery: "training_core", name: "TLV NOTAM / Airport Closures", rpc: "aviation/v1/list-airport-delays", selector: "TLV", auth: "apiKey", tags: ["israel", "notam", "aviation"], rationale: "Captures Ben Gurion disruption, closure, and severe airspace changes.", }), scrapeSource({ id: "israel-gpsjam-levant", agentId: "israel", delivery: "training_core", name: "GPSJam Levant View", url: "https://gpsjam.org", allowlistStatus: "external", tags: ["israel", "ew", "gps-jamming"], rationale: "Electronic-warfare and GNSS-spoofing conditions in the Levant.", }), videoSource({ id: "israel-kan11-live", agentId: "israel", delivery: "live_demo", name: "Kan 11 Live", channel: "@KAN11NEWS", tags: ["israel", "live", "hebrew-tv"], rationale: "Hebrew live-news situational awareness.", }), videoSource({ id: "israel-i24-live", agentId: "israel", delivery: "live_demo", name: "i24NEWS Live", channel: "@i24NEWS_HE", tags: ["israel", "live", "tv"], rationale: "Israeli TV framing and rapid local updates.", }), videoSource({ id: "israel-jerusalem-webcam", agentId: "israel", delivery: "live_demo", name: "Jerusalem Webcam", channel: "@JerusalemLive", tags: ["israel", "live", "webcam"], rationale: "Civilian and symbolic city-center visual context.", }), videoSource({ id: "israel-tel-aviv-webcam", agentId: "israel", delivery: "live_demo", name: "Tel Aviv Webcam", channel: "@IsraelLiveCam", tags: ["israel", "live", "webcam"], rationale: "Urban impact visibility during escalation demos.", }), telegramSource({ id: "israel-defender-dome", agentId: "israel", delivery: "training_core", name: "The Defender Dome", handle: "DefenderDome", tags: ["israel", "telegram", "air-defense"], rationale: "Fast conflict monitoring stream centered on missile-defense and strike reporting.", }), telegramSource({ id: "israel-yedioth-news", agentId: "israel", delivery: "training_core", name: "Yedioth News", handle: "yediotnews25", tags: ["israel", "telegram", "breaking"], rationale: "Israeli breaking-news lane with local reaction and casualty reporting.", }), rssSource({ id: "israel-jerusalem-post", agentId: "israel", delivery: "training_core", name: "Jerusalem Post", url: "https://www.jpost.com/Rss/RssFeedsHeadlines.aspx", allowlistStatus: "allowed", tags: ["israel", "english", "breaking"], rationale: "Fast English-language Israeli headlines with domestic and diplomatic framing.", }), rssSource({ id: "israel-times-of-israel", agentId: "israel", delivery: "training_core", name: "The Times of Israel", url: "https://www.timesofisrael.com/feed/", allowlistStatus: "allowed", tags: ["israel", "local-reporting", "politics"], rationale: "Fast Israel-specific political and security coverage with local context.", }), rssSource({ id: "israel-ynet-english", agentId: "israel", delivery: "training_core", name: "Ynet English", url: googleNewsSearchUrl("site:ynetnews.com Israel"), allowlistStatus: "allowed", tags: ["israel", "english", "domestic"], rationale: "Broad Israeli domestic and security coverage in English.", notes: FALLBACK_QUERY_NOTE, }), rssSource({ id: "israel-israel-hayom", agentId: "israel", delivery: "training_core", name: "Israel Hayom", url: "https://www.israelhayom.com/feed/", allowlistStatus: "allowed", tags: ["israel", "domestic", "politics"], rationale: "Mainstream Israeli political and security framing with high local salience.", }), rssSource({ id: "israel-middle-east-eye", agentId: "israel", delivery: "training_core", name: "Middle East Eye", url: "https://www.middleeasteye.net/rss", allowlistStatus: "allowed", tags: ["israel", "regional", "media"], rationale: "Regional reaction and adversarial framing around Israeli actions.", }), rssSource({ id: "israel-al-monitor", agentId: "israel", delivery: "training_core", name: "Al-Monitor", url: "https://www.al-monitor.com/rss", allowlistStatus: "allowed", tags: ["israel", "regional", "analysis"], rationale: "Cross-border political-security analysis with strong Middle East context.", }), rssSource({ id: "israel-debka", agentId: "israel", delivery: "training_core", name: "Debka", url: googleNewsSearchUrl("site:debka.com Israel security"), allowlistStatus: "allowed", tags: ["israel", "security", "osint"], rationale: "Israel-focused security and intelligence reporting lane.", notes: FALLBACK_QUERY_NOTE, }), rssSource({ id: "israel-memri", agentId: "israel", delivery: "training_core", name: "MEMRI", url: googleNewsSearchUrl("site:memri.org MEMRI Middle East"), allowlistStatus: "allowed", tags: ["israel", "mena-monitoring", "translation"], rationale: "Regional media and rhetoric monitoring relevant to Israeli decision-making.", notes: FALLBACK_QUERY_NOTE, }), rssSource({ id: "israel-ict-terrorism", agentId: "israel", delivery: "training_core", name: "ICT Terrorism", url: "https://www.ict.org.il/rss", allowlistStatus: "allowed", tags: ["israel", "terrorism", "research"], rationale: "Counterterrorism analysis and incident context tied to Israeli security policy.", }), rssSource({ id: "israel-calcalist", agentId: "israel", delivery: "training_core", name: "Calcalist", url: googleNewsSearchUrl("site:calcalistech.com Israel tech economy"), allowlistStatus: "allowed", tags: ["israel", "economy", "tech"], rationale: "Israeli tech-economy and business continuity signal under crisis pressure.", notes: FALLBACK_QUERY_NOTE, }), rssSource({ id: "israel-globes", agentId: "israel", delivery: "training_core", name: "Globes", url: googleNewsSearchUrl('site:en.globes.co.il OR site:globes.co.il Israel business'), allowlistStatus: "allowed", tags: ["israel", "economy", "markets"], rationale: "Israeli business and market sentiment tied to wartime resilience.", notes: FALLBACK_QUERY_NOTE, }), rssSource({ id: "israel-un-middle-east", agentId: "israel", delivery: "training_core", name: "UN Middle East", url: "https://news.un.org/feed/subscribe/en/news/region/middle-east/feed/rss.xml", allowlistStatus: "allowed", tags: ["israel", "diplomacy", "un"], rationale: "UN regional diplomatic context, resolutions, and humanitarian framing.", }), rssSource({ id: "israel-reuters-middle-east", agentId: "israel", delivery: "training_core", name: "Reuters Middle East", url: googleNewsSearchUrl('site:reuters.com "Middle East" Israel Iran Lebanon'), allowlistStatus: "allowed", tags: ["israel", "wire", "regional"], rationale: "Wire-grade regional headline stream around Israel, Iran, and the Levant.", notes: FALLBACK_QUERY_NOTE, }), worldMonitorSource({ id: "israel-theater-posture", agentId: "israel", delivery: "training_core", name: "Levant Theater Posture", rpc: "military/v1/get-theater-posture", selector: "levant", kind: "api", tags: ["israel", "military", "posture"], rationale: "Regional force posture snapshot across Israel's immediate operating theater.", }), worldMonitorSource({ id: "israel-military-bases", agentId: "israel", delivery: "training_core", name: "Israel Frontier Base Layer", rpc: "military/v1/list-military-bases", selector: "israel-frontier", kind: "api", tags: ["israel", "bases", "readiness"], rationale: "Static force-infrastructure layer for front-line readiness reasoning.", }), worldMonitorSource({ id: "israel-eastern-med-warnings", agentId: "israel", delivery: "training_core", name: "Eastern Med Navigational Warnings", rpc: "maritime/v1/list-navigational-warnings", selector: "eastern-med", kind: "api", tags: ["israel", "maritime", "warnings"], rationale: "Detects maritime safety and exclusion-zone changes around the Eastern Mediterranean.", }), worldMonitorSource({ id: "israel-northern-border-incidents", agentId: "israel", delivery: "training_core", name: "Northern Border Incident Tracker", rpc: "conflict/v1/list-acled-events", selector: "south-lebanon-galilee", tags: ["israel", "north-border", "conflict-events"], rationale: "Structured launch, infiltration, and strike-event lane for the Lebanon-Galilee border fight.", }), worldMonitorSource({ id: "israel-northern-strike-heat", agentId: "israel", delivery: "training_core", name: "Northern Strike Heat", rpc: "wildfire/v1/list-fire-detections", selector: "north-israel-lebanon", tags: ["israel", "thermal", "strike-verification"], rationale: "Thermal proxy for launch areas, strike aftermath, and persistent fire activity on the northern front.", }), worldMonitorSource({ id: "israel-syrian-transfer-watch", agentId: "israel", delivery: "training_core", name: "Syrian Transfer Corridor Watch", rpc: "conflict/v1/list-acled-events", selector: "syria-transfer-corridor", tags: ["israel", "syria", "weapons-transfer"], rationale: "Tracks corridor activity tied to Iranian reinforcement, air-defense movement, and precision-weapon transfer.", }), worldMonitorSource({ id: "israel-northern-air-defense", agentId: "israel", delivery: "training_core", name: "Northern Air Defense Readiness", rpc: "military/v1/get-theater-posture", selector: "israel-air-defense", kind: "api", tags: ["israel", "air-defense", "readiness"], rationale: "Operational posture layer for interceptor coverage, warning quality, and defensive readiness in the north.", }), telegramSource({ id: "iran-vahid-online", agentId: "iran", delivery: "training_core", name: "VahidOnline", handle: "VahidOnline", tags: ["iran", "telegram", "politics"], rationale: "High-signal Iran political and social monitoring from the curated Telegram set.", }), rssSource({ id: "iran-bbc-persian", agentId: "iran", delivery: "training_core", name: "BBC Persian", url: "http://feeds.bbci.co.uk/persian/tv-and-radio-37434376/rss.xml", allowlistStatus: "allowed", tags: ["iran", "persian", "opposition"], rationale: "Persian-language reporting from a distinct narrative lane.", }), rssSource({ id: "iran-iran-international", agentId: "iran", delivery: "training_core", name: "Iran International", url: "https://news.google.com/rss/search?q=site:iranintl.com+when:2d&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["iran", "opposition", "crisis"], rationale: "High-signal exile-media coverage of Iranian crisis conditions.", }), rssSource({ id: "iran-fars-news", agentId: "iran", delivery: "training_core", name: "Fars News", url: "https://news.google.com/rss/search?q=site:farsnews.ir+when:2d&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["iran", "state", "security"], rationale: "State-adjacent narrative and official-security framing.", }), worldMonitorSource({ id: "iran-liveuamap-events", agentId: "iran", delivery: "training_core", name: "LiveUAMap Iran Events", rpc: "conflict/v1/list-iran-events", auth: "relay", tags: ["iran", "map-events", "strikes"], rationale: "Geocoded attacks, strikes, and military incidents focused on Iran.", }), worldMonitorSource({ id: "iran-nasa-firms", agentId: "iran", delivery: "training_core", name: "NASA FIRMS Strike Heat", rpc: "wildfire/v1/list-fire-detections", selector: "IR", kind: "api", tags: ["iran", "thermal", "damage"], rationale: "Satellite thermal proxy for strike damage and industrial disruption.", }), telegramSource({ id: "iran-fotros-resistance", agentId: "iran", delivery: "training_core", name: "Fotros Resistance", handle: "FotrosResistancee", tags: ["iran", "telegram", "proxy-network"], rationale: "Proxy-aligned conflict signal from inside the resistance ecosystem.", }), videoSource({ id: "iran-iranintl-live", agentId: "iran", delivery: "live_demo", name: "Iran International Live", channel: "@IranIntl", tags: ["iran", "live", "tv"], rationale: "Live narrative pulse for Iranian crisis coverage.", }), videoSource({ id: "iran-tehran-webcam", agentId: "iran", delivery: "live_demo", name: "Tehran Webcam", channel: "@IranHDCams", tags: ["iran", "live", "webcam"], rationale: "Visual monitoring of Tehran during live sessions.", }), telegramSource({ id: "iran-iranintl-telegram", agentId: "iran", delivery: "training_core", name: "Iran International Telegram", handle: "iranintltv", tags: ["iran", "telegram", "opposition"], rationale: "Low-latency opposition and exile-media alerts in Telegram form.", }), telegramSource({ id: "iran-bno-news", agentId: "iran", delivery: "training_core", name: "BNO News", handle: "BNONews", tags: ["iran", "telegram", "breaking"], rationale: "Fast global breaking-news lane for strike and escalation confirmation.", }), rssSource({ id: "iran-al-arabiya", agentId: "iran", delivery: "training_core", name: "Al Arabiya", url: "https://news.google.com/rss/search?q=site:english.alarabiya.net+when:2d&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["iran", "regional", "arab-media"], rationale: "Arab regional framing of Iranian retaliation, strikes, and diplomacy.", }), rssSource({ id: "iran-nuclear-energy-watch", agentId: "iran", delivery: "training_core", name: "Iran Nuclear Energy Watch", url: "https://news.google.com/rss/search?q=(Iran+IAEA+OR+Iran+uranium+OR+Iran+%22nuclear+energy%22)+when:3d&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["iran", "nuclear", "iaea"], rationale: "Dedicated nuclear and safeguards signal relevant to escalation thresholds.", }), worldMonitorSource({ id: "iran-internet-outages", agentId: "iran", delivery: "training_core", name: "Iran Internet Outages", rpc: "infrastructure/v1/list-internet-outages", selector: "IR", kind: "api", tags: ["iran", "infrastructure", "internet"], rationale: "Tracks censorship, disruption, and wartime communications degradation.", }), worldMonitorSource({ id: "iran-unrest-events", agentId: "iran", delivery: "training_core", name: "Iran Unrest Events", rpc: "unrest/v1/list-unrest-events", selector: "IR", kind: "api", tags: ["iran", "unrest", "domestic"], rationale: "Crowd action, protests, and unrest pressure affecting regime stability.", }), worldMonitorSource({ id: "iran-climate-anomalies", agentId: "iran", delivery: "training_core", name: "Iran Climate Anomalies", rpc: "climate/v1/list-climate-anomalies", selector: "IR", kind: "api", tags: ["iran", "climate", "stress"], rationale: "Environmental stressor layer that can compound logistics and domestic strain.", }), worldMonitorSource({ id: "iran-stock-index", agentId: "iran", delivery: "training_core", name: "Iran Stock Index", rpc: "market/v1/get-country-stock-index", selector: "IR", kind: "api", tags: ["iran", "markets", "macro"], rationale: "Market-stress proxy for domestic confidence and sanctions shock.", }), videoSource({ id: "iran-trt-world-live", agentId: "iran", delivery: "live_demo", name: "TRT World Live", channel: "@TRTWorld", tags: ["iran", "live", "regional-media"], rationale: "External live regional coverage of Iranian crisis developments.", }), videoSource({ id: "iran-cgtn-arabic-live", agentId: "iran", delivery: "live_demo", name: "CGTN Arabic Live", channel: "@CGTNArabic", tags: ["iran", "live", "regional-media"], rationale: "Alternative non-Western broadcast lane for Iranian events.", }), videoSource({ id: "iran-france24-live", agentId: "iran", delivery: "live_demo", name: "France 24 Live", channel: "@FRANCE24", tags: ["iran", "live", "global-media"], rationale: "European live-news framing for Iranian escalation and diplomatic fallout.", }), telegramSource({ id: "hezbollah-abu-ali", agentId: "hezbollah", delivery: "training_core", name: "Abu Ali Express", handle: "abualiexpress", tags: ["hezbollah", "telegram", "proxy"], rationale: "Fast proxy-aligned updates focused on the Levant theater.", }), telegramSource({ id: "hezbollah-abu-ali-en", agentId: "hezbollah", delivery: "training_core", name: "Abu Ali Express EN", handle: "englishabuali", tags: ["hezbollah", "telegram", "proxy", "english"], rationale: "English-readable mirror of the proxy operational narrative.", }), telegramSource({ id: "hezbollah-lebanon-update", agentId: "hezbollah", delivery: "training_core", name: "Lebanon Update", handle: "LebUpdate", tags: ["hezbollah", "telegram", "lebanon"], rationale: "Lebanon-specific breaking updates for theater awareness.", }), telegramSource({ id: "hezbollah-middle-east-spectator", agentId: "hezbollah", delivery: "training_core", name: "Middle East Spectator", handle: "Middle_East_Spectator", tags: ["hezbollah", "telegram", "osint"], rationale: "OSINT-style regional conflict monitoring aligned with proxy reasoning.", }), telegramSource({ id: "hezbollah-the-cradle", agentId: "hezbollah", delivery: "training_core", name: "The Cradle", handle: "thecradlemedia", tags: ["hezbollah", "telegram", "regional-politics"], rationale: "Resistance-axis narrative and regional political framing.", }), worldMonitorSource({ id: "hezbollah-acled-lebanon-syria", agentId: "hezbollah", delivery: "training_core", name: "ACLED Lebanon/Syria Conflict Events", rpc: "conflict/v1/list-acled-events", selector: "LB,SY", auth: "apiKey", tags: ["hezbollah", "acled", "theater-events"], rationale: "Event-level escalation tracking around Hezbollah's operating theater.", }), videoSource({ id: "hezbollah-beirut-webcam", agentId: "hezbollah", delivery: "live_demo", name: "Beirut MTV Lebanon Webcam", channel: "@MTVLebanonNews", tags: ["hezbollah", "live", "webcam"], rationale: "Lebanese urban situational awareness during live sessions.", }), telegramSource({ id: "hezbollah-middle-east-now", agentId: "hezbollah", delivery: "training_core", name: "Middle East Now Breaking", handle: "MiddleEastNow_Breaking", tags: ["hezbollah", "telegram", "breaking"], rationale: "Rapid regional conflict alerts with strong Levant focus.", }), telegramSource({ id: "hezbollah-aurora-intel", agentId: "hezbollah", delivery: "training_core", name: "Aurora Intel", handle: "AuroraIntel", tags: ["hezbollah", "telegram", "conflict"], rationale: "Fast OSINT and military-incident feed useful for proxy-theater awareness.", }), telegramSource({ id: "hezbollah-osintdefender", agentId: "hezbollah", delivery: "training_core", name: "OSINTdefender", handle: "OSINTdefender", tags: ["hezbollah", "telegram", "osint"], rationale: "High-frequency conflict monitoring and strike verification stream.", }), telegramSource({ id: "hezbollah-osintops-news", agentId: "hezbollah", delivery: "training_core", name: "OSIntOps News", handle: "Osintlatestnews", tags: ["hezbollah", "telegram", "osint"], rationale: "Additional raw conflict reporting lane for cross-checking border activity.", }), telegramSource({ id: "hezbollah-osint-live", agentId: "hezbollah", delivery: "training_core", name: "OSINT Live", handle: "osintlive", tags: ["hezbollah", "telegram", "osint"], rationale: "Low-latency conflict snapshots across the wider resistance theater.", }), worldMonitorSource({ id: "hezbollah-humanitarian-summary", agentId: "hezbollah", delivery: "training_core", name: "Lebanon Humanitarian Summary", rpc: "conflict/v1/get-humanitarian-summary", selector: "LBN", kind: "api", tags: ["hezbollah", "humanitarian", "lebanon"], rationale: "Civilian-pressure signal relevant to Hezbollah's operating environment inside Lebanon.", }), worldMonitorSource({ id: "hezbollah-unrest-lebanon", agentId: "hezbollah", delivery: "training_core", name: "Lebanon Unrest Events", rpc: "unrest/v1/list-unrest-events", selector: "LB", kind: "api", tags: ["hezbollah", "unrest", "lebanon"], rationale: "Captures protests and domestic pressure that shape Hezbollah's political room.", }), worldMonitorSource({ id: "hezbollah-internet-outages", agentId: "hezbollah", delivery: "training_core", name: "Lebanon Internet Outages", rpc: "infrastructure/v1/list-internet-outages", selector: "LB", kind: "api", tags: ["hezbollah", "infrastructure", "internet"], rationale: "Communications-disruption proxy for domestic stress and wartime degradation.", }), worldMonitorSource({ id: "hezbollah-climate-anomalies", agentId: "hezbollah", delivery: "training_core", name: "Lebanon Climate Anomalies", rpc: "climate/v1/list-climate-anomalies", selector: "LB", kind: "api", tags: ["hezbollah", "climate", "stress"], rationale: "Environmental strain layer that can worsen humanitarian and logistics pressure.", }), worldMonitorSource({ id: "hezbollah-lebanon-coast-warnings", agentId: "hezbollah", delivery: "training_core", name: "Lebanon Coast Navigational Warnings", rpc: "maritime/v1/list-navigational-warnings", selector: "lebanon-coast", kind: "api", tags: ["hezbollah", "maritime", "coast"], rationale: "Coastal maritime-warning layer relevant to Beirut and southern Lebanese littoral activity.", }), worldMonitorSource({ id: "hezbollah-blue-line-incidents", agentId: "hezbollah", delivery: "training_core", name: "Blue Line Incident Tracker", rpc: "conflict/v1/list-acled-events", selector: "blue-line", tags: ["hezbollah", "blue-line", "conflict-events"], rationale: "Structured incident feed for launch, raid, and interdiction patterns along the Blue Line.", }), worldMonitorSource({ id: "hezbollah-south-lebanon-strike-heat", agentId: "hezbollah", delivery: "training_core", name: "South Lebanon Strike Heat", rpc: "wildfire/v1/list-fire-detections", selector: "south-lebanon", tags: ["hezbollah", "thermal", "strike-verification"], rationale: "Thermal strike-verification layer for launch areas, bombardment zones, and fire persistence in south Lebanon.", }), worldMonitorSource({ id: "hezbollah-bekaa-transit-watch", agentId: "hezbollah", delivery: "training_core", name: "Bekaa Transit Corridor Watch", rpc: "conflict/v1/list-acled-events", selector: "bekaa-syria-corridor", tags: ["hezbollah", "bekaa", "logistics-corridor"], rationale: "Tracks corridor disruptions, interdiction, and sustainment movement between the Bekaa and Syria.", }), rssSource({ id: "gulf-arabian-business", agentId: "gulf", delivery: "training_core", name: "Arabian Business", url: "https://news.google.com/rss/search?q=site:arabianbusiness.com+(Saudi+Arabia+OR+UAE+OR+GCC)+when:7d&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["gulf", "business", "gcc"], rationale: "GCC business and investment coverage.", }), rssSource({ id: "gulf-the-national-gcc", agentId: "gulf", delivery: "training_core", name: "The National (GCC Query Set)", url: "https://news.google.com/rss/search?q=site:thenationalnews.com+(Abu+Dhabi+OR+UAE+OR+Saudi)+when:7d&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["gulf", "uae", "regional"], rationale: "UAE and GCC political-economic framing.", }), rssSource({ id: "gulf-gulf-investments", agentId: "gulf", delivery: "training_core", name: "Gulf Investments", url: "https://news.google.com/rss/search?q=(%22Saudi+Arabia%22+OR+%22UAE%22+OR+%22Abu+Dhabi%22)+investment+infrastructure+when:7d&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["gulf", "investments", "infrastructure"], rationale: "Saudi/UAE investment and infrastructure signal.", }), worldMonitorSource({ id: "gulf-gulf-quotes", agentId: "gulf", delivery: "training_core", name: "Gulf Economies Panel", rpc: "market/v1/list-gulf-quotes", kind: "api", tags: ["gulf", "markets", "currencies"], rationale: "GCC indices, currencies, and oil-linked quotes in one bundle.", }), worldMonitorSource({ id: "gulf-oil-energy", agentId: "gulf", delivery: "training_core", name: "Oil and Energy Analytics", rpc: "market/v1/list-commodity-quotes", selector: "oil-energy-analytics", kind: "api", tags: ["gulf", "oil", "energy"], rationale: "WTI, Brent, and related energy-market stress relevant to Gulf hedging.", }), worldMonitorSource({ id: "gulf-chokepoint-status", agentId: "gulf", delivery: "training_core", name: "Maritime Chokepoint Disruption Panel", rpc: "supply-chain/v1/get-chokepoint-status", kind: "api", tags: ["gulf", "shipping", "hormuz"], rationale: "Strait of Hormuz and nearby chokepoint disruption risk from AIS-linked signals.", }), worldMonitorSource({ id: "gulf-fdi-layer", agentId: "gulf", delivery: "training_core", name: "Gulf FDI Layer", rpc: "economic/v1/list-gulf-fdi", kind: "structured", tags: ["gulf", "fdi", "capital-flows"], rationale: "Regional leverage and overseas economic exposure.", }), videoSource({ id: "gulf-sky-news-arabia-live", agentId: "gulf", delivery: "live_demo", name: "Sky News Arabia Live", channel: "@skynewsarabia", tags: ["gulf", "live", "tv"], rationale: "Arab-region live coverage from a Gulf-aligned lens.", }), videoSource({ id: "gulf-mecca-webcam", agentId: "gulf", delivery: "live_demo", name: "Mecca Webcam", channel: "@MakkahLive", tags: ["gulf", "live", "webcam"], rationale: "Symbolic and social-stability context in the Saudi sphere.", }), rssSource({ id: "gulf-arab-news", agentId: "gulf", delivery: "training_core", name: "Arab News", url: "https://news.google.com/rss/search?q=site:arabnews.com+when:7d&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["gulf", "saudi", "regional"], rationale: "Saudi-facing regional political and economic coverage.", }), rssSource({ id: "gulf-reuters-business", agentId: "gulf", delivery: "training_core", name: "Reuters Business", url: "https://news.google.com/rss/search?q=site:reuters.com+business+markets&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["gulf", "markets", "wire"], rationale: "Global business-market reporting that captures oil and shipping spillovers.", }), rssSource({ id: "gulf-cnbc", agentId: "gulf", delivery: "training_core", name: "CNBC", url: "https://www.cnbc.com/id/100003114/device/rss/rss.html", allowlistStatus: "allowed", tags: ["gulf", "markets", "broadcast"], rationale: "Fast financial-media coverage of energy and market volatility.", }), rssSource({ id: "gulf-yahoo-finance", agentId: "gulf", delivery: "training_core", name: "Yahoo Finance", url: "https://finance.yahoo.com/news/rssindex", allowlistStatus: "allowed", tags: ["gulf", "markets", "portfolio"], rationale: "Broad market and commodity feed for GCC hedging behavior.", }), worldMonitorSource({ id: "gulf-shipping-rates", agentId: "gulf", delivery: "training_core", name: "Shipping Rates Monitor", rpc: "supply-chain/v1/get-shipping-rates", kind: "api", tags: ["gulf", "shipping", "rates"], rationale: "Freight-cost signal tied to Red Sea and Hormuz disruptions.", }), worldMonitorSource({ id: "gulf-critical-minerals", agentId: "gulf", delivery: "training_core", name: "Critical Minerals Monitor", rpc: "supply-chain/v1/get-critical-minerals", kind: "api", tags: ["gulf", "minerals", "supply-chain"], rationale: "Strategic materials view relevant to industrial and sovereign hedging decisions.", }), worldMonitorSource({ id: "gulf-trade-restrictions", agentId: "gulf", delivery: "training_core", name: "Trade Restrictions Monitor", rpc: "trade/v1/get-trade-restrictions", kind: "api", tags: ["gulf", "trade", "restrictions"], rationale: "Tracks active restrictions that can reshape Gulf commercial routing.", }), worldMonitorSource({ id: "gulf-tariff-trends", agentId: "gulf", delivery: "training_core", name: "Tariff Trends Monitor", rpc: "trade/v1/get-tariff-trends", kind: "api", tags: ["gulf", "trade", "tariffs"], rationale: "Trade-policy trendline for longer-horizon Gulf coalition planning.", }), videoSource({ id: "gulf-al-arabiya-live", agentId: "gulf", delivery: "live_demo", name: "Al Arabiya Live", channel: "@AlArabiya", tags: ["gulf", "live", "regional-media"], rationale: "Gulf-aligned live television coverage during regional escalation.", }), videoSource({ id: "gulf-aljazeera-arabic-live", agentId: "gulf", delivery: "live_demo", name: "Al Jazeera Arabic Live", channel: "@AljazeeraChannel", tags: ["gulf", "live", "regional-media"], rationale: "Countervailing Arab broadcast lane for live narrative competition.", }), videoSource({ id: "gulf-middle-east-webcam", agentId: "gulf", delivery: "live_demo", name: "Middle East Regional Webcam", channel: "@MiddleEastCams", tags: ["gulf", "live", "webcam"], rationale: "Regional multicam view for symbolic and urban stability checks in demos.", }), worldMonitorSource({ id: "oversight-cii", agentId: "oversight", delivery: "training_core", name: "Country Instability Index (CII)", rpc: "intelligence/v1/get-risk-scores", selector: "cii", kind: "api", tags: ["oversight", "meta", "instability"], rationale: "Global instability baseline across countries and time.", }), worldMonitorSource({ id: "oversight-hotspot-escalation", agentId: "oversight", delivery: "training_core", name: "Hotspot Escalation Score", rpc: "intelligence/v1/get-risk-scores", selector: "hotspot-escalation", kind: "api", tags: ["oversight", "meta", "hotspots"], rationale: "Detects areas where multiple signals are converging into escalation.", }), worldMonitorSource({ id: "oversight-strategic-risk", agentId: "oversight", delivery: "training_core", name: "Strategic Risk Score", rpc: "intelligence/v1/get-risk-scores", selector: "strategic-risk", kind: "api", tags: ["oversight", "meta", "risk"], rationale: "High-level risk estimate for intervention timing.", }), worldMonitorSource({ id: "oversight-cross-stream-correlation", agentId: "oversight", delivery: "training_core", name: "Cross-Stream Correlation Engine", rpc: "intelligence/v1/get-risk-scores", selector: "cross-stream-correlation", kind: "structured", tags: ["oversight", "meta", "correlation"], rationale: "Finds multi-signal patterns single actors may miss.", }), worldMonitorSource({ id: "oversight-intelligence-gap-tracker", agentId: "oversight", delivery: "training_core", name: "Intelligence Gap Tracker", rpc: "intelligence/v1/get-risk-scores", selector: "data-freshness", kind: "structured", tags: ["oversight", "meta", "freshness"], rationale: "Flags stale or missing critical signals to prevent false confidence.", }), worldMonitorSource({ id: "oversight-headline-memory-brief", agentId: "oversight", delivery: "training_core", name: "Headline Memory / World Brief / AI Deduction", rpc: "intelligence/v1/get-country-intel-brief", selector: "headline-memory-world-brief", kind: "structured", tags: ["oversight", "meta", "ai-brief"], rationale: "Synthesized cross-source reasoning layer for oversight explanations.", }), worldMonitorSource({ id: "oversight-hapi-displacement", agentId: "oversight", delivery: "training_core", name: "HAPI Displacement Data", rpc: "displacement/v1/get-displacement-summary", kind: "api", tags: ["oversight", "humanitarian", "displacement"], rationale: "Civilian displacement and humanitarian stress signal.", }), worldMonitorSource({ id: "oversight-worldpop-exposure", agentId: "oversight", delivery: "training_core", name: "WorldPop Population Exposure", rpc: "displacement/v1/get-population-exposure", kind: "api", tags: ["oversight", "humanitarian", "population"], rationale: "Estimates likely civilian exposure around conflict or disaster events.", }), worldMonitorSource({ id: "oversight-security-advisories", agentId: "oversight", delivery: "training_core", name: "Security Advisories Aggregation", rpc: "intelligence/v1/get-risk-scores", selector: "security-advisories", kind: "structured", tags: ["oversight", "humanitarian", "advisories"], rationale: "Government and health-risk warning layer that acts as an external guardrail.", }), worldMonitorSource({ id: "oversight-ucdp-events", agentId: "oversight", delivery: "training_core", name: "UCDP Conflict Events", rpc: "conflict/v1/list-ucdp-events", selector: "global", kind: "api", tags: ["oversight", "conflict", "events"], rationale: "Global conflict-event baseline for cross-theater escalation monitoring.", }), worldMonitorSource({ id: "oversight-natural-events", agentId: "oversight", delivery: "training_core", name: "Natural Events Monitor", rpc: "natural/v1/list-natural-events", selector: "global", kind: "api", tags: ["oversight", "natural", "events"], rationale: "Cross-domain disaster layer that can interact with conflict systems.", }), worldMonitorSource({ id: "oversight-earthquakes", agentId: "oversight", delivery: "training_core", name: "Earthquakes Feed", rpc: "seismology/v1/list-earthquakes", selector: "global", kind: "api", tags: ["oversight", "seismology", "events"], rationale: "Global earthquake monitoring for compounding humanitarian and infrastructure risk.", }), worldMonitorSource({ id: "oversight-internet-outages", agentId: "oversight", delivery: "training_core", name: "Internet Outages Baseline", rpc: "infrastructure/v1/list-internet-outages", selector: "global", kind: "api", tags: ["oversight", "infrastructure", "internet"], rationale: "System-wide communications degradation layer for detecting hidden crises.", }), worldMonitorSource({ id: "oversight-cable-health", agentId: "oversight", delivery: "training_core", name: "Cable Health Advisory Layer", rpc: "infrastructure/v1/get-cable-health", selector: "global", kind: "api", tags: ["oversight", "infrastructure", "cables"], rationale: "Undersea cable health and warning layer for systemic resilience monitoring.", }), worldMonitorSource({ id: "oversight-climate-anomalies", agentId: "oversight", delivery: "training_core", name: "Climate Anomalies Monitor", rpc: "climate/v1/list-climate-anomalies", selector: "global", kind: "api", tags: ["oversight", "climate", "stress"], rationale: "Global climate anomalies that may amplify instability and humanitarian risk.", }), worldMonitorSource({ id: "oversight-cyber-threats", agentId: "oversight", delivery: "training_core", name: "Cyber Threats Feed", rpc: "cyber/v1/list-cyber-threats", selector: "global", kind: "api", tags: ["oversight", "cyber", "threats"], rationale: "Cross-border cyber IOC layer for latent escalation and infrastructure risk.", }), worldMonitorSource({ id: "oversight-feed-digest", agentId: "oversight", delivery: "training_core", name: "Feed Digest Aggregator", rpc: "news/v1/list-feed-digest", selector: "oversight-digest", kind: "structured", tags: ["oversight", "news", "digest"], rationale: "Deduplicated multi-feed digest for broad situational awareness.", }), worldMonitorSource({ id: "oversight-gdelt-search", agentId: "oversight", delivery: "training_core", name: "GDELT Document Search", rpc: "intelligence/v1/search-gdelt-documents", selector: "global-escalation", kind: "structured", tags: ["oversight", "gdelt", "documents"], rationale: "Cross-source document search to detect emerging event clusters and narratives.", }), worldMonitorSource({ id: "oversight-pizzint-status", agentId: "oversight", delivery: "training_core", name: "Pizzint Status", rpc: "intelligence/v1/get-pizzint-status", selector: "oversight-watch", kind: "structured", tags: ["oversight", "meta", "watch"], rationale: "Supplementary anomaly signal for unusual activity and open-source chatter shifts.", }), rssSource({ id: "oversight-unhcr-feed", agentId: "oversight", delivery: "live_demo", name: "UNHCR Feed", url: "https://news.google.com/rss/search?q=site:unhcr.org+OR+UNHCR+refugees+when:3d&hl=en-US&gl=US&ceid=US:en", allowlistStatus: "allowed", tags: ["oversight", "live", "humanitarian"], rationale: "Live humanitarian trend visibility during monitored sessions.", }), ]; export const AGENT_SOURCE_REGISTRY: Record = { us: sources.filter((source) => source.agentId === "us"), israel: sources.filter((source) => source.agentId === "israel"), iran: sources.filter((source) => source.agentId === "iran"), hezbollah: sources.filter((source) => source.agentId === "hezbollah"), gulf: sources.filter((source) => source.agentId === "gulf"), oversight: sources.filter((source) => source.agentId === "oversight"), }; export function getSourcesForAgent(agentId: AgentId, delivery?: SourceDelivery): DataSourceSpec[] { const sourcesForAgent = AGENT_SOURCE_REGISTRY[agentId]; if (!delivery) { return sourcesForAgent; } return sourcesForAgent.filter((source) => source.delivery === delivery); } export function getTrainingSourcesForAgent(agentId: AgentId): DataSourceSpec[] { return getSourcesForAgent(agentId, "training_core"); } export function getLiveSourcesForAgent(agentId: AgentId): DataSourceSpec[] { return getSourcesForAgent(agentId, "live_demo"); } export function getAllSources(): DataSourceSpec[] { return sources; }