Spaces:
Running on Zero
Running on Zero
GitHub Actions
feat: WebLLM browser agent with PeerJS mesh, HybridRAG, news signals, and easter-egg ticker
78cc96f | // src/news/signals.js | |
| // Keyword-based signal scoring. Signals are ALERTS, not assertions of fact. | |
| export const SIGNALS = [ | |
| { name: "war", keywords: ["airstrike", "mobilization", "missile", "ceasefire", "front line", "shelling", "invasion"] }, | |
| { name: "cyber", keywords: ["breach", "ransomware", "exploit", "leak", "hacker", "zero-day", "data breach"] }, | |
| { name: "space", keywords: ["solar flare", "cme", "geomagnetic storm", "space weather", "sun eruption", "aurora"] }, | |
| { name: "aviation", keywords: ["airport closure", "ground stop", "flight diversion", "emergency landing", "near miss"] }, | |
| { name: "earth", keywords: ["earthquake", "tsunami", "volcano", "eruption", "magnitude"] }, | |
| { name: "finance", keywords: ["market crash", "circuit breaker", "default", "bank run", "bailout"] }, | |
| ]; | |
| export function scoreSignals(items, extraSignals = []) { | |
| const all = [...SIGNALS, ...extraSignals]; | |
| return all.map((s) => { | |
| let score = 0; | |
| const hits = []; | |
| for (const it of items) { | |
| const t = `${it.title || ""} ${it.summary || ""} ${it.source || ""}`.toLowerCase(); | |
| for (const k of s.keywords) { | |
| if (t.includes(k.toLowerCase())) { | |
| score += 1; | |
| if (hits.length < 5) hits.push(it.title); | |
| } | |
| } | |
| } | |
| return { ...s, score, active: score > 0, hits }; | |
| }); | |
| } | |
| // User-defined alerts (keyword clusters) — CRUD via localStorage. | |
| const ALERT_KEY = "hearthnet_alerts"; | |
| export function loadAlerts() { | |
| try { | |
| return JSON.parse(localStorage.getItem(ALERT_KEY) || "[]"); | |
| } catch { | |
| return []; | |
| } | |
| } | |
| export function saveAlerts(alerts) { | |
| localStorage.setItem(ALERT_KEY, JSON.stringify(alerts)); | |
| } | |
| export function addAlert(name, keywordsCsv) { | |
| const alerts = loadAlerts(); | |
| const keywords = keywordsCsv.split(",").map((k) => k.trim()).filter(Boolean); | |
| alerts.push({ name, keywords }); | |
| saveAlerts(alerts); | |
| return alerts; | |
| } | |
| export function removeAlert(name) { | |
| const alerts = loadAlerts().filter((a) => a.name !== name); | |
| saveAlerts(alerts); | |
| return alerts; | |
| } | |